Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Mikolaï Krol
erp5
Commits
9f2212cf
Commit
9f2212cf
authored
Dec 16, 2014
by
wenjie.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ERP5WorkflowMethod class created, correct all workflow5 indacation to ERP5Workflow.
parent
6dbab7ce
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
221 additions
and
97 deletions
+221
-97
product/ERP5Type/Base.py
product/ERP5Type/Base.py
+197
-70
product/ERP5Type/ERP5Type.py
product/ERP5Type/ERP5Type.py
+7
-6
product/ERP5Type/dynamic/lazy_class.py
product/ERP5Type/dynamic/lazy_class.py
+7
-11
product/ERP5Workflow/Document/Workflow.py
product/ERP5Workflow/Document/Workflow.py
+10
-10
No files found.
product/ERP5Type/Base.py
View file @
9f2212cf
...
@@ -109,6 +109,7 @@ _MARKER = []
...
@@ -109,6 +109,7 @@ _MARKER = []
global
registered_workflow_method_set
global
registered_workflow_method_set
wildcard_interaction_method_id_match
=
re
.
compile
(
r'[[.?*+{(\\]'
).
search
wildcard_interaction_method_id_match
=
re
.
compile
(
r'[[.?*+{(\\]'
).
search
workflow_method_registry
=
[]
# XXX A set() would be better but would require a hash in WorkflowMethod class
workflow_method_registry
=
[]
# XXX A set() would be better but would require a hash in WorkflowMethod class
erp5workflow_method_registry
=
[]
def
resetRegisteredWorkflowMethod
(
portal_type
=
None
):
def
resetRegisteredWorkflowMethod
(
portal_type
=
None
):
"""
"""
...
@@ -117,8 +118,14 @@ def resetRegisteredWorkflowMethod(portal_type=None):
...
@@ -117,8 +118,14 @@ def resetRegisteredWorkflowMethod(portal_type=None):
for
method
in
workflow_method_registry
:
for
method
in
workflow_method_registry
:
method
.
reset
(
portal_type
=
portal_type
)
method
.
reset
(
portal_type
=
portal_type
)
class
WorkflowMethod
(
Method
):
def
resetRegisteredERP5WorkflowMethod
(
portal_type
=
None
):
"""
TODO: unwrap workflow methos which were standard methods initially
"""
for
method
in
erp5workflow_method_registry
:
method
.
reset
(
portal_type
=
portal_type
)
class
ERP5WorkflowMethod
(
Method
):
def
__init__
(
self
,
method
,
id
=
None
,
reindex
=
1
):
def
__init__
(
self
,
method
,
id
=
None
,
reindex
=
1
):
"""
"""
method - a callable object or a method
method - a callable object or a method
...
@@ -182,7 +189,7 @@ class WorkflowMethod(Method):
...
@@ -182,7 +189,7 @@ class WorkflowMethod(Method):
for
wf_id
,
transition_list
in
invoke_once_dict
.
iteritems
():
for
wf_id
,
transition_list
in
invoke_once_dict
.
iteritems
():
valid_transition_list
=
[]
valid_transition_list
=
[]
for
transition_id
in
transition_list
:
for
transition_id
in
transition_list
:
once_transition_key
=
(
'Products.ERP5Type.Base.WorkflowMethod.__call__'
,
once_transition_key
=
(
'Products.ERP5Type.Base.
ERP5
WorkflowMethod.__call__'
,
wf_id
,
transition_id
,
instance_path
)
wf_id
,
transition_id
,
instance_path
)
once_transition_dict
[(
wf_id
,
transition_id
)]
=
once_transition_key
once_transition_dict
[(
wf_id
,
transition_id
)]
=
once_transition_key
if
once_transition_key
not
in
transactional_variable
:
if
once_transition_key
not
in
transactional_variable
:
...
@@ -198,32 +205,132 @@ class WorkflowMethod(Method):
...
@@ -198,32 +205,132 @@ class WorkflowMethod(Method):
if
not
candidate_transition_item_list
:
if
not
candidate_transition_item_list
:
return
apply
(
self
.
__dict__
[
'_m'
],
(
instance
,)
+
args
,
kw
)
return
apply
(
self
.
__dict__
[
'_m'
],
(
instance
,)
+
args
,
kw
)
#=============== Workflow5 Project, Wenjie, Dec 2014 =====================
if
instance
.
getTypeInfo
().
getTypeWorkflowList
():
### Access the ERP5Type workflow_list
if
instance
.
getTypeInfo
().
getTypeWorkflowList
()
!=
[]:
wf5_module
=
instance
.
getPortalObject
().
getDefaultModule
(
portal_type
=
"Workflow"
)
wf5_module
=
instance
.
getPortalObject
().
getDefaultModule
(
portal_type
=
"Workflow"
)
### Build the list of method which is call and will be invoked.
### Build the list of method which is call and will be invoked.
valid_transition_item_list
=
[]
valid_transition_item_list
=
[]
for
wf_id
,
transition_list
in
candidate_transition_item_list
:
for
wf_id
,
transition_list
in
candidate_transition_item_list
:
valid_list
=
[]
valid_list
=
[]
for
transition_id
in
transition_list
:
for
transition_id
in
transition_list
:
if
wf5_module
.
_getOb
(
wf_id
).
is
Workflow5
MethodSupported
(
instance
,
wf5_module
.
_getOb
(
wf_id
).
_getOb
(
transition_id
)):
if
wf5_module
.
_getOb
(
wf_id
).
is
ERP5Workflow
MethodSupported
(
instance
,
wf5_module
.
_getOb
(
wf_id
).
_getOb
(
transition_id
)):
#if wf5_module._getOb(wf_id)._getOb(transition_id) in instance.getCategoryStateValue().getDestinationValueList():
#if wf5_module._getOb(wf_id)._getOb(transition_id) in instance.getCategoryStateValue().getDestinationValueList():
valid_list
.
append
(
transition_id
)
valid_list
.
append
(
transition_id
)
once_transition_key
=
once_transition_dict
.
get
((
wf_id
,
transition_id
))
once_transition_key
=
once_transition_dict
.
get
((
wf_id
,
transition_id
))
transactional_variable
[
once_transition_key
]
=
1
transactional_variable
[
once_transition_key
]
=
1
else
:
#else: ### don't do anything if no supported
raise
UnsupportedWorkflowMethod
(
instance
,
wf_id
,
transition_id
)
#
raise UnsupportedWorkflowMethod(instance, wf_id, transition_id)
if
valid_list
:
if
valid_list
:
valid_transition_item_list
.
append
((
wf_id
,
valid_list
))
valid_transition_item_list
.
append
((
wf_id
,
valid_list
))
### Execute method
### Execute method
for
wf_id
,
transition_list
in
valid_transition_item_list
:
for
wf_id
,
transition_list
in
valid_transition_item_list
:
for
tr
in
transition_list
:
for
tr
in
transition_list
:
#raise NotImplementedError (tr)
method5
=
wf5_module
.
_getOb
(
wf_id
).
_getOb
(
tr
)
method5
=
wf5_module
.
_getOb
(
wf_id
).
_getOb
(
tr
)
method5
.
execute
(
instance
)
method5
.
execute
(
instance
)
#=================================== wf5 =================================
def
registerERP5TransitionAlways
(
self
,
portal_type
,
workflow_id
,
transition_id
):
"""
Transitions registered as always will be invoked always
"""
transition_list
=
self
.
_invoke_always
.
setdefault
(
portal_type
,
{}).
setdefault
(
workflow_id
,
[])
if
transition_id
not
in
transition_list
:
transition_list
.
append
(
transition_id
)
self
.
registerERP5
()
def
registerERP5TransitionOncePerTransaction
(
self
,
portal_type
,
workflow_id
,
transition_id
):
"""
Transitions registered as one per transactions will be invoked
only once per transaction
"""
transition_list
=
self
.
_invoke_once
.
setdefault
(
portal_type
,
{}).
setdefault
(
workflow_id
,
[])
if
transition_id
not
in
transition_list
:
transition_list
.
append
(
transition_id
)
self
.
registerERP5
()
def
registerERP5
(
self
):
"""
Registers the method so that _aq_reset may later reset it
"""
erp5workflow_method_registry
.
append
(
self
)
class
WorkflowMethod
(
Method
):
def
__init__
(
self
,
method
,
id
=
None
,
reindex
=
1
):
"""
method - a callable object or a method
id - the workflow transition id. This is useful
to emulate "old" CMF behaviour but is
somehow inconsistent with the new registration based
approach implemented here.
We store id as _transition_id and use it
to register the transition for each portal
type and each workflow for which it is
applicable.
"""
self
.
_m
=
method
if
id
is
None
:
self
.
_transition_id
=
method
.
__name__
else
:
self
.
_transition_id
=
id
# Only publishable methods can be published as interactions
# A pure private method (ex. _doNothing) can not be published
# This is intentional to prevent methods such as submit, share to
# be called from a URL. If someone can show that this way
# is wrong (ex. for remote operation of a site), let us know.
if
not
method
.
__name__
.
startswith
(
'_'
):
self
.
__name__
=
method
.
__name__
for
func_id
in
[
'func_code'
,
'func_defaults'
,
'func_dict'
,
'func_doc'
,
'func_globals'
,
'func_name'
]:
setattr
(
self
,
func_id
,
getattr
(
method
,
func_id
,
None
))
self
.
_invoke_once
=
{}
self
.
_invoke_always
=
{}
# Store in a dict all workflow IDs which require to
# invoke wrapWorkflowMethod at every call
# during the same transaction
def
getTransitionId
(
self
):
return
self
.
_transition_id
def
__call__
(
self
,
instance
,
*
args
,
**
kw
):
"""
Invoke the wrapped method, and deal with the results.
"""
if
getattr
(
self
,
'__name__'
,
None
)
in
(
'getPhysicalPath'
,
'getId'
):
# To prevent infinite recursion, 2 methods must have special treatment
# this is clearly not the best way to implement this but it is
# already better than what we had. I (JPS) would prefer to use
# critical sections in this part of the code and a
# thread variable which tells in which semantic context the code
# should be executed. - XXX
return
self
.
_m
(
instance
,
*
args
,
**
kw
)
# Build a list of transitions which may need to be invoked
instance_path
=
instance
.
getPhysicalPath
()
portal_type
=
instance
.
portal_type
transactional_variable
=
getTransactionalVariable
()
invoke_once_dict
=
self
.
_invoke_once
.
get
(
portal_type
,
{})
valid_invoke_once_item_list
=
[]
# Only keep those transitions which were never invoked
once_transition_dict
=
{}
# New implementation does not use any longer wrapWorkflowMethod
# but directly calls the workflow methods
for
wf_id
,
transition_list
in
invoke_once_dict
.
iteritems
():
valid_transition_list
=
[]
for
transition_id
in
transition_list
:
once_transition_key
=
(
'Products.ERP5Type.Base.WorkflowMethod.__call__'
,
wf_id
,
transition_id
,
instance_path
)
once_transition_dict
[(
wf_id
,
transition_id
)]
=
once_transition_key
if
once_transition_key
not
in
transactional_variable
:
valid_transition_list
.
append
(
transition_id
)
if
valid_transition_list
:
valid_invoke_once_item_list
.
append
((
wf_id
,
valid_transition_list
))
candidate_transition_item_list
=
valid_invoke_once_item_list
+
\
self
.
_invoke_always
.
get
(
portal_type
,
{}).
items
()
#LOG('candidate_transition_item_list %s' % self.__name__, 0, str(candidate_transition_item_list))
# Try to return immediately if there are no transition to invoke
if
not
candidate_transition_item_list
:
return
apply
(
self
.
__dict__
[
'_m'
],
(
instance
,)
+
args
,
kw
)
# Prepare a list of transitions which should be invoked.
# Prepare a list of transitions which should be invoked.
# This list is based on the results of isWorkflowMethodSupported.
# This list is based on the results of isWorkflowMethodSupported.
...
@@ -231,69 +338,66 @@ class WorkflowMethod(Method):
...
@@ -231,69 +338,66 @@ class WorkflowMethod(Method):
# Otherwise, an exception is raised if the workflow transition does not
# Otherwise, an exception is raised if the workflow transition does not
# exist from the current state, or if the guard rejects it.
# exist from the current state, or if the guard rejects it.
try
:
try
:
try
:
wf
=
getattr
(
instance
.
getPortalObject
(),
'portal_workflow'
)
# portal_workflow is a list!
wf
=
getattr
(
instance
.
getPortalObject
(),
'portal_workflow'
)
# portal_workflow is a list!
except
AttributeError
:
except
AttributeError
:
# XXX instance is unwrapped(no acquisition)
# XXX instance is unwrapped(no acquisition)
# XXX I must think that what is a correct behavior.(Yusei)
# XXX I must think that what is a correct behavior.(Yusei)
return
self
.
_m
(
instance
,
*
args
,
**
kw
)
return
self
.
_m
(
instance
,
*
args
,
**
kw
)
valid_transition_item_list
=
[]
valid_transition_item_list
=
[]
for
wf_id
,
transition_list
in
candidate_transition_item_list
:
for
wf_id
,
transition_list
in
candidate_transition_item_list
:
valid_list
=
[]
valid_list
=
[]
candidate_workflow
=
wf
[
wf_id
]
candidate_workflow
=
wf
[
wf_id
]
for
transition_id
in
transition_list
:
for
transition_id
in
transition_list
:
if
candidate_workflow
.
isWorkflowMethodSupported
(
instance
,
transition_id
):
if
candidate_workflow
.
isWorkflowMethodSupported
(
instance
,
transition_id
):
valid_list
.
append
(
transition_id
)
valid_list
.
append
(
transition_id
)
once_transition_key
=
once_transition_dict
.
get
((
wf_id
,
transition_id
))
once_transition_key
=
once_transition_dict
.
get
((
wf_id
,
transition_id
))
if
once_transition_key
:
if
once_transition_key
:
# a run-once transition, prevent it from running again in
# a run-once transition, prevent it from running again in
# the same transaction
# the same transaction
transactional_variable
[
once_transition_key
]
=
1
transactional_variable
[
once_transition_key
]
=
1
elif
candidate_workflow
.
__class__
.
__name__
==
'DCWorkflowDefinition'
:
elif
candidate_workflow
.
__class__
.
__name__
==
'DCWorkflowDefinition'
:
raise
UnsupportedWorkflowMethod
(
instance
,
wf_id
,
transition_id
)
raise
UnsupportedWorkflowMethod
(
instance
,
wf_id
,
transition_id
)
# XXX Keep the log for projects that needs to comment out
# XXX Keep the log for projects that needs to comment out
# the previous line.
# the previous line.
LOG
(
"WorkflowMethod.__call__"
,
ERROR
,
LOG
(
"WorkflowMethod.__call__"
,
ERROR
,
"Transition %s/%s on %r is ignored. Current state is %r."
"Transition %s/%s on %r is ignored. Current state is %r."
%
(
wf_id
,
transition_id
,
instance
,
%
(
wf_id
,
transition_id
,
instance
,
candidate_workflow
.
_getWorkflowStateOf
(
instance
,
id_only
=
1
)))
candidate_workflow
.
_getWorkflowStateOf
(
instance
,
id_only
=
1
)))
if
valid_list
:
if
valid_list
:
valid_transition_item_list
.
append
((
wf_id
,
valid_list
))
valid_transition_item_list
.
append
((
wf_id
,
valid_list
))
#LOG('valid_transition_item_list %s' % self.__name__, 0, str(valid_transition_item_list))
#LOG('valid_transition_item_list %s' % self.__name__, 0, str(valid_transition_item_list))
# Call whatever must be called before changing states
# Call whatever must be called before changing states
for
wf_id
,
transition_list
in
valid_transition_item_list
:
for
wf_id
,
transition_list
in
valid_transition_item_list
:
wf
[
wf_id
].
notifyBefore
(
instance
,
transition_list
,
args
=
args
,
kw
=
kw
)
wf
[
wf_id
].
notifyBefore
(
instance
,
transition_list
,
args
=
args
,
kw
=
kw
)
# Compute expected result
# Compute expected result
result
=
apply
(
self
.
__dict__
[
'_m'
],
(
instance
,)
+
args
,
kw
)
result
=
apply
(
self
.
__dict__
[
'_m'
],
(
instance
,)
+
args
,
kw
)
# Change the state of statefull workflows
# Change the state of statefull workflows
for
wf_id
,
transition_list
in
valid_transition_item_list
:
for
wf_id
,
transition_list
in
valid_transition_item_list
:
try
:
try
:
wf
[
wf_id
].
notifyWorkflowMethod
(
instance
,
transition_list
,
args
=
args
,
kw
=
kw
)
wf
[
wf_id
].
notifyWorkflowMethod
(
instance
,
transition_list
,
args
=
args
,
kw
=
kw
)
except
ObjectDeleted
:
except
ObjectDeleted
:
# Re-raise with a different result.
# Re-raise with a different result.
raise
ObjectDeleted
(
result
)
raise
ObjectDeleted
(
result
)
except
ObjectMoved
,
ex
:
except
ObjectMoved
,
ex
:
# Re-raise with a different result.
# Re-raise with a different result.
raise
ObjectMoved
(
ex
.
getNewObject
(),
result
)
raise
ObjectMoved
(
ex
.
getNewObject
(),
result
)
# Call whatever must be called after changing states
# Call whatever must be called after changing states
for
wf_id
,
transition_list
in
valid_transition_item_list
:
for
wf_id
,
transition_list
in
valid_transition_item_list
:
# /product/ERP5/InteractionWorkflow.py, update value, provide info
# /product/ERP5/InteractionWorkflow.py, update value, provide info
wf
[
wf_id
].
notifySuccess
(
instance
,
transition_list
,
result
,
args
=
args
,
kw
=
kw
)
wf
[
wf_id
].
notifySuccess
(
instance
,
transition_list
,
result
,
args
=
args
,
kw
=
kw
)
# Return result finally
# Return result finally
return
result
return
result
# Interactions should not be disabled during normal operation. Only in very
# Interactions should not be disabled during normal operation. Only in very
# rare and specific cases like data migration. That's why it is implemented
# rare and specific cases like data migration. That's why it is implemented
# with temporary monkey-patching, instead of slowing down __call__ with yet
# with temporary monkey-patching, instead of slowing down __call__ with yet
# another condition.
# another condition.
except
:
pass
_do_interaction
=
__call__
_do_interaction
=
__call__
_no_interaction_lock
=
threading
.
Lock
()
_no_interaction_lock
=
threading
.
Lock
()
_no_interaction_log
=
None
_no_interaction_log
=
None
...
@@ -378,6 +482,7 @@ def _aq_reset():
...
@@ -378,6 +482,7 @@ def _aq_reset():
class
PropertyHolder
(
object
):
class
PropertyHolder
(
object
):
isRADContent
=
1
isRADContent
=
1
WORKFLOW_METHOD_MARKER
=
(
'Base._doNothing'
,)
WORKFLOW_METHOD_MARKER
=
(
'Base._doNothing'
,)
ERP5WORKFLOW_METHOD_MARKER
=
(
'Base._doNothing'
,)
RESERVED_PROPERTY_SET
=
set
((
'_constraints'
,
'_properties'
,
'_categories'
,
RESERVED_PROPERTY_SET
=
set
((
'_constraints'
,
'_properties'
,
'_categories'
,
'__implements__'
,
'property_sheets'
,
'__implements__'
,
'property_sheets'
,
'__ac_permissions__'
,
'__ac_permissions__'
,
...
@@ -387,6 +492,7 @@ class PropertyHolder(object):
...
@@ -387,6 +492,7 @@ class PropertyHolder(object):
self
.
__name__
=
name
self
.
__name__
=
name
self
.
security
=
ClassSecurityInfo
()
# We create a new security info object
self
.
security
=
ClassSecurityInfo
()
# We create a new security info object
self
.
workflow_method_registry
=
{}
self
.
workflow_method_registry
=
{}
self
.
erp5workflow_method_registry
=
{}
self
.
_categories
=
[]
self
.
_categories
=
[]
self
.
_properties
=
[]
self
.
_properties
=
[]
...
@@ -414,6 +520,23 @@ class PropertyHolder(object):
...
@@ -414,6 +520,23 @@ class PropertyHolder(object):
wf_id
,
wf_id
,
tr_id
)
tr_id
)
def
registerERP5WorkflowMethod
(
self
,
id
,
wf_id
,
tr_id
,
once_per_transaction
=
0
):
portal_type
=
self
.
portal_type
ERP5workflow_method
=
getattr
(
self
,
id
,
None
)
if
ERP5workflow_method
is
None
:
# XXX: We should pass 'tr_id' as second parameter.
ERP5workflow_method
=
ERP5WorkflowMethod
(
Base
.
_doNothing
)
setattr
(
self
,
id
,
ERP5workflow_method
)
if
once_per_transaction
:
ERP5workflow_method
.
registerERP5TransitionOncePerTransaction
(
portal_type
,
wf_id
,
tr_id
)
else
:
ERP5workflow_method
.
registerERP5TransitionAlways
(
portal_type
,
wf_id
,
tr_id
)
def
declareProtected
(
self
,
permission
,
accessor_name
):
def
declareProtected
(
self
,
permission
,
accessor_name
):
"""
"""
It is possible to gain 30% of accessor RAM footprint
It is possible to gain 30% of accessor RAM footprint
...
@@ -461,12 +584,26 @@ class PropertyHolder(object):
...
@@ -461,12 +584,26 @@ class PropertyHolder(object):
or
(
isinstance
(
x
[
1
],
types
.
TupleType
)
or
(
isinstance
(
x
[
1
],
types
.
TupleType
)
and
x
[
1
]
is
PropertyHolder
.
WORKFLOW_METHOD_MARKER
)]
and
x
[
1
]
is
PropertyHolder
.
WORKFLOW_METHOD_MARKER
)]
def
getERP5WorkflowMethodItemList
(
self
):
"""
Return a list of tuple (id, method) for every workflow method
"""
return
[
x
for
x
in
self
.
_getPropertyHolderItemList
()
if
isinstance
(
x
[
1
],
ERP5WorkflowMethod
)
or
(
isinstance
(
x
[
1
],
types
.
TupleType
)
and
x
[
1
]
is
PropertyHolder
.
ERP5WORKFLOW_METHOD_MARKER
)]
def
getWorkflowMethodIdList
(
self
):
def
getWorkflowMethodIdList
(
self
):
"""
"""
Return the list of workflow method IDs
Return the list of workflow method IDs
"""
"""
return
[
x
[
0
]
for
x
in
self
.
getWorkflowMethodItemList
()]
return
[
x
[
0
]
for
x
in
self
.
getWorkflowMethodItemList
()]
def
getERP5WorkflowMethodIdList
(
self
):
"""
Return the list of workflow method IDs
"""
return
[
x
[
0
]
for
x
in
self
.
getERP5WorkflowMethodItemList
()]
def
_getClassDict
(
self
,
klass
,
inherited
=
1
,
local
=
1
):
def
_getClassDict
(
self
,
klass
,
inherited
=
1
,
local
=
1
):
"""
"""
Return a dict for every property of a class
Return a dict for every property of a class
...
@@ -522,26 +659,26 @@ def getClassPropertyList(klass):
...
@@ -522,26 +659,26 @@ def getClassPropertyList(klass):
if
p
not
in
ps_list
])
if
p
not
in
ps_list
])
return
ps_list
return
ps_list
# ===================
Workflow5
Project, Wenjie, Dec 2014 ======================
# ===================
ERP5Workflow
Project, Wenjie, Dec 2014 ======================
### this function will be used in /product/ERP5Type/dynamic/lazy_class.py
### this function will be used in /product/ERP5Type/dynamic/lazy_class.py
### in generatePortalTypeAccessors()
### in generatePortalTypeAccessors()
def
intializePortalTypeERP5WorkflowMethod
(
ptype_klass
,
portal_
workflow5
):
def
intializePortalTypeERP5WorkflowMethod
(
ptype_klass
,
portal_
ERP5Workflow
):
### portal_
workflow5
is the entire ERP5Workflow module, need to access the
### portal_
ERP5Workflow
is the entire ERP5Workflow module, need to access the
### workflow_list from instance's portal type. So only the related erp5 workflow will be used.
### workflow_list from instance's portal type. So only the related erp5 workflow will be used.
wf5_module
=
aq_inner
(
portal_
workflow5
)
wf5_module
=
aq_inner
(
portal_
ERP5Workflow
)
portal_type
=
portal_
workflow5
.
getPortalObject
().
getDefaultModule
(
portal_type
=
"portal_types"
)
portal_type
=
portal_
ERP5Workflow
.
getPortalObject
().
getDefaultModule
(
portal_type
=
"portal_types"
)
pt
=
portal_type
.
_getOb
(
ptype_klass
.
__name__
)
pt
=
portal_type
.
_getOb
(
ptype_klass
.
__name__
)
#raise NotImplementedError (portal_type)
#raise NotImplementedError (portal_type)
#raise NotImplementedError (wf5_module)#<Workflow Module at workflow_module>
#raise NotImplementedError (wf5_module)#<Workflow Module at workflow_module>
### creat workflow method:
### creat workflow method:
for
workflow5
in
pt
.
workflow_list
:
for
ERP5Workflow
in
pt
.
workflow_list
:
for
tr
in
wf5_module
.
_getOb
(
workflow5
).
objectValues
(
portal_type
=
"Transition"
):
for
tr
in
wf5_module
.
_getOb
(
ERP5Workflow
).
objectValues
(
portal_type
=
"Transition"
):
tr_id
=
tr
.
id
tr_id
=
tr
.
id
method_id
=
convertToMixedCase
(
tr_id
)
method_id
=
convertToMixedCase
(
tr_id
)
wf_id
=
workflow5
wf_id
=
ERP5Workflow
ptype_klass
.
registerWorkflowMethod
(
method_id
,
wf_id
,
tr_id
,
0
)
ptype_klass
.
register
ERP5
WorkflowMethod
(
method_id
,
wf_id
,
tr_id
,
0
)
#ptype_klass.security.declareProtected(Permissions.AccessContentsInformation,
#ptype_klass.security.declareProtected(Permissions.AccessContentsInformation,
# method_id)
# method_id)
#ptype_klass.registerWorkflowMethod(method_id, wf_id, tr_id)
#ptype_klass.registerWorkflowMethod(method_id, wf_id, tr_id)
...
@@ -552,18 +689,6 @@ def intializePortalTypeERP5WorkflowMethod(ptype_klass, portal_workflow5):
...
@@ -552,18 +689,6 @@ def intializePortalTypeERP5WorkflowMethod(ptype_klass, portal_workflow5):
# method_id)
# method_id)
# ptype_klass.registerWorkflowMethod(method_id, wf_id, tr_id, 0)
# ptype_klass.registerWorkflowMethod(method_id, wf_id, tr_id, 0)
# continue
# continue
""" ### useless at this stage, dec 2014
# Wrap method
if not callable(method):
LOG('initializePortalTypeERP5WorkflowMethods', 100,
'WARNING! Can not initialize %s on %s' %
\
(method_id, portal_type))
continue
if not isinstance(method, WorkflowMethod):
method = WorkflowMethod(method)
setattr(ptype_klass, method_id, method)
#ptype_klass.registerWorkflowMethod(method_id, wf_id, tr_id)
"""
#method.registerTransitionAlways(portal_type, wf_id, tr_id)
#method.registerTransitionAlways(portal_type, wf_id, tr_id)
# =================== WF5 ======================================================
# =================== WF5 ======================================================
...
@@ -3529,3 +3654,5 @@ class TempBase(Base):
...
@@ -3529,3 +3654,5 @@ class TempBase(Base):
# allow_class(TempBase) in ERP5Type/Document/__init__.py will trample our
# allow_class(TempBase) in ERP5Type/Document/__init__.py will trample our
# ClassSecurityInfo with one that doesn't declare our public methods
# ClassSecurityInfo with one that doesn't declare our public methods
InitializeClass
(
TempBase
)
InitializeClass
(
TempBase
)
product/ERP5Type/ERP5Type.py
View file @
9f2212cf
...
@@ -418,13 +418,14 @@ class ERP5TypeInformation(XMLObject,
...
@@ -418,13 +418,14 @@ class ERP5TypeInformation(XMLObject,
for
workflow
in
workflow_tool
.
getWorkflowsFor
(
ob
):
for
workflow
in
workflow_tool
.
getWorkflowsFor
(
ob
):
workflow
.
notifyCreated
(
ob
)
workflow
.
notifyCreated
(
ob
)
### Project WORKFLOW5 , WENJIE , 2014 ###
# =========== Project ERP5Workflow , WENJIE , 2014 ================================
### workflow_list need to be defined somewhere.
for
workflow5
in
self
.
getTypeWorkflowList
():
### exp: ERP5Workflow in Person module won't work at this situation.
for
ERP5Workflow
in
self
.
getTypeWorkflowList
():
workflow_module
=
portal
.
getDefaultModule
(
portal_type
=
"Workflow"
)
workflow_module
=
portal
.
getDefaultModule
(
portal_type
=
"Workflow"
)
workflow5
=
workflow_module
.
_getOb
(
workflow5
)
ERP5Workflow
=
workflow_module
.
_getOb
(
ERP5Workflow
)
workflow5
.
initializeDocument
(
ob
)
ERP5Workflow
.
initializeDocument
(
ob
)
# =========== WF5 ==============================================================
if
not
temp_object
:
if
not
temp_object
:
init_script
=
self
.
getTypeInitScriptId
()
init_script
=
self
.
getTypeInitScriptId
()
...
...
product/ERP5Type/dynamic/lazy_class.py
View file @
9f2212cf
...
@@ -266,26 +266,22 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
...
@@ -266,26 +266,22 @@ class PortalTypeMetaClass(GhostBaseMetaClass, PropertyHolder):
else
:
else
:
initializePortalTypeDynamicWorkflowMethods
(
cls
,
portal_workflow
)
initializePortalTypeDynamicWorkflowMethods
(
cls
,
portal_workflow
)
# ================== Workflow5 Project, Wenjie, Dec 2014 =======================
# ================== ERP5Workflow Project, Wenjie, Dec 2014 =======================
### the ERP5Workflow list is defined in ERP5Type, only try to get erp5workflow
### when it's an erp5workflow related type.
portal_type
=
site
.
getDefaultModule
(
portal_type
=
"portal_types"
)
portal_type
=
site
.
getDefaultModule
(
portal_type
=
"portal_types"
)
### try to get workflow_list from related types then initialize the class of types
### try to get workflow_list from related types then initialize the class of types
try
:
try
:
pt
=
portal_type
.
_getOb
(
cls
.
__name__
)
pt
=
portal_type
.
_getOb
(
cls
.
__name__
)
#raise NotImplemented (pt)
#raise NotImplemented (pt)
if
hasattr
(
pt
,
'workflow_list'
):
if
hasattr
(
pt
,
'workflow_list'
):
#if cls.__name__ == "Object Type": # Has to be redifined
### Get ERP5Workflow Module
portal_workflow5
=
site
.
getDefaultModule
(
portal_type
=
"Workflow"
)
portal_ERP5Workflow
=
site
.
getDefaultModule
(
portal_type
=
"Workflow"
)
#raise NotImplementedError (portal_workflow5) #<Workflow Module at workflow_module>
if
portal_ERP5Workflow
is
None
:
#raise NotImplementedError (cls.__module__) #<class 'erp5.portal_type.Category Property'>
if
portal_workflow5
is
None
:
LOG
(
"ERP5Type.Dynamic"
,
WARNING
,
LOG
(
"ERP5Type.Dynamic"
,
WARNING
,
"no
workflow5
methods for %s"
"no
ERP5Workflow
methods for %s"
%
cls
.
__name__
)
%
cls
.
__name__
)
else
:
else
:
intializePortalTypeERP5WorkflowMethod
(
cls
,
portal_workflow5
)
### Generate Workflow Method
intializePortalTypeERP5WorkflowMethod
(
cls
,
portal_ERP5Workflow
)
except
:
except
:
pass
pass
# ================== WF5 =======================================================
# ================== WF5 =======================================================
...
...
product/ERP5Workflow/Document/Workflow.py
View file @
9f2212cf
...
@@ -55,7 +55,7 @@ class Workflow(XMLObject):
...
@@ -55,7 +55,7 @@ class Workflow(XMLObject):
isRADContent
=
1
isRADContent
=
1
### register the variable given by "base category value"
### register the variable given by "base category value"
#state_var = 'state'
#state_var = 'state'
### In DCworkflow; state/transition can be registered inside workflow
### In DCworkflow; state/transition can be registered inside workflow
# Declarative security
# Declarative security
security
=
ClassSecurityInfo
()
security
=
ClassSecurityInfo
()
...
@@ -143,25 +143,25 @@ class Workflow(XMLObject):
...
@@ -143,25 +143,25 @@ class Workflow(XMLObject):
transition
=
transition
,
transition
=
transition
,
transition_url
=
transition_url
,
transition_url
=
transition_url
,
state
=
state
)
state
=
state
)
# ==========
Workflow5
Project, Wenjie, Dec 2014 ===============================
# ==========
ERP5Workflow
Project, Wenjie, Dec 2014 ===============================
def
is
Workflow5
MethodSupported
(
self
,
document
,
transition
):
def
is
ERP5Workflow
MethodSupported
(
self
,
document
,
transition
):
s
tate
=
self
.
_getWorkflow5
StateOf
(
document
)
s
def
=
self
.
_getERP5Workflow
StateOf
(
document
)
if
s
tate
is
None
:
if
s
def
is
None
:
return
0
return
0
if
transition
in
s
tate
.
getDestinationValueList
():
if
transition
in
s
def
.
getDestinationValueList
():
return
1
return
1
return
0
return
0
### get workflow state from base category value:
### get workflow state from base category value:
def
_get
Workflow5
StateOf
(
self
,
ob
):
def
_get
ERP5Workflow
StateOf
(
self
,
ob
):
bc_id
=
self
.
getStateBaseCategory
()
bc_id
=
self
.
getStateBaseCategory
()
state_path
=
ob
.
getCategoryList
()
state_path
=
ob
.
getCategoryList
()
state_path
=
state_path
[
0
].
lstrip
(
"%s/"
%
bc_id
)
state_path
=
state_path
[
0
].
lstrip
(
"%s/"
%
bc_id
)
###
###
if
state_path
is
not
None
:
if
state_path
is
not
None
:
s
tate
=
self
.
restrictedTraverse
(
state_path
)
s
def
=
self
.
restrictedTraverse
(
state_path
)
else
:
s
tate
=
None
else
:
s
def
=
None
return
s
tate
return
s
def
# =========== WF5 ==============================================================
# =========== WF5 ==============================================================
###########
###########
## Graph ##
## Graph ##
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment