diff --git a/frappe/model/workflow.py b/frappe/model/workflow.py index b134f2f8dc..3f3711af9d 100644 --- a/frappe/model/workflow.py +++ b/frappe/model/workflow.py @@ -45,20 +45,29 @@ def get_transitions(doc, workflow = None, raise_exception=False): transitions = [] for transition in workflow.transitions: if transition.state == current_state and transition.allowed in roles: - if transition.condition: - # if condition, evaluate - # access to frappe.db.get_value and frappe.db.get_list - success = frappe.safe_eval(transition.condition, - dict(frappe = frappe._dict( - db = frappe._dict(get_value = frappe.db.get_value, get_list=frappe.db.get_list), - session = frappe.session - )), - dict(doc = doc)) - if not success: - continue + if not is_transition_condition_satisfied(transition, doc): + continue transitions.append(transition.as_dict()) return transitions +def get_workflow_safe_globals(): + # access to frappe.db.get_value and frappe.db.get_list + return dict( + frappe=frappe._dict( + db=frappe._dict( + get_value=frappe.db.get_value, + get_list=frappe.db.get_list + ), + session=frappe.session + ) + ) + +def is_transition_condition_satisfied(transition, doc): + if not transition.condition: + return True + else: + return frappe.safe_eval(transition.condition, get_workflow_safe_globals(), dict(doc=doc.as_dict())) + @frappe.whitelist() def apply_workflow(doc, action): '''Allow workflow action on the current doc''' diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 3d4c106f29..68ee7cd2ef 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -9,8 +9,8 @@ from frappe.utils import get_url, get_datetime from frappe.desk.form.utils import get_pdf_link from frappe.utils.verified_command import get_signed_params, verify_request from frappe import _ -from frappe.model.workflow import apply_workflow, get_workflow_name, \ - has_approval_access, get_workflow_state_field, send_email_alert, get_workflow_field_value +from frappe.model.workflow import apply_workflow, get_workflow_name, has_approval_access, \ + get_workflow_state_field, send_email_alert, get_workflow_field_value, is_transition_condition_satisfied from frappe.desk.notifications import clear_doctype_notifications from frappe.utils.user import get_users_with_role @@ -155,10 +155,10 @@ def get_next_possible_transitions(workflow_name, state, doc=None): for transition in transitions: is_next_state_optional = get_state_optional_field_value(workflow_name, transition.next_state) # skip transition if next state of the transition is optional - if transition.condition and not frappe.safe_eval(transition.condition, None, {'doc': doc.as_dict()}): - continue if is_next_state_optional: continue + if not is_transition_condition_satisfied(transition, doc): + continue transitions_to_return.append(transition) return transitions_to_return