84 lines
3.2 KiB
Python
84 lines
3.2 KiB
Python
from django.db import transaction
|
|
from app.models import Workflow, StepAction, Rule
|
|
from app.workflow_registry import ACTION_REGISTRY, validate_action_schema
|
|
from app.workflow_utils import resolve_value
|
|
|
|
@transaction.atomic
|
|
def execute_step(step: StepAction, context: dict):
|
|
print(f"\n>>> EXECUTING STEP: {step.step_code} (Order: {step.order})")
|
|
|
|
# Evaluate rules first
|
|
for rule in step.rules.filter(is_active=True):
|
|
if not evaluate_rule(rule, context):
|
|
print(f"Step {step.step_code} skipped due to rule failure.")
|
|
return {"step": step.step_code, "skipped": True, "reason": "rule_failed"}
|
|
|
|
results = []
|
|
# Lưu ý: step.actions thường là một list các dict
|
|
actions_list = step.actions if isinstance(step.actions, list) else []
|
|
|
|
for action in actions_list:
|
|
action_type = action.get("type")
|
|
params = action.get("params", {})
|
|
|
|
print(f" - Action Type: {action_type}")
|
|
|
|
if action_type not in ACTION_REGISTRY:
|
|
print(f" - ERROR: Action type '{action_type}' not registered!")
|
|
continue
|
|
|
|
try:
|
|
validate_action_schema(action_type, params)
|
|
handler = ACTION_REGISTRY[action_type]
|
|
|
|
# Thực thi handler
|
|
output = handler(params, context)
|
|
|
|
results.append({"action": action_type, "result": output})
|
|
|
|
# Lưu output cuối cùng vào context
|
|
context["last_result"] = output
|
|
except Exception as e:
|
|
print(f" - ERROR in action {action_type}: {str(e)}")
|
|
# Raise để transaction.atomic rollback nếu cần, hoặc xử lý tùy ý
|
|
raise e
|
|
|
|
return {"step": step.step_code, "executed": True, "results": results}
|
|
|
|
|
|
def evaluate_rule(rule: Rule, context: dict):
|
|
for condition in (rule.conditions or []):
|
|
left = resolve_value(condition.get("left"), context)
|
|
right = resolve_value(condition.get("right"), context)
|
|
op = condition.get("operator", "==")
|
|
|
|
print(f" Evaluating Rule: {left} {op} {right}")
|
|
|
|
if op == "IN" and left not in right: return False
|
|
if op == "==" and left != right: return False
|
|
if op == "!=" and left == right: return False
|
|
if op == ">" and not (left > right): return False
|
|
if op == "<" and not (left < right): return False
|
|
|
|
return True
|
|
|
|
|
|
def run_workflow(workflow_code: str, trigger: str, context: dict):
|
|
print(f"\n================ START WORKFLOW: {workflow_code} ================")
|
|
print(f"Trigger: {trigger} | Initial Context: {context}")
|
|
|
|
workflow = Workflow.objects.filter(code=workflow_code, is_active=True).first()
|
|
if not workflow:
|
|
print(f"Workflow '{workflow_code}' not found or inactive.")
|
|
raise Exception(f"Workflow '{workflow_code}' not found")
|
|
|
|
steps = workflow.steps.filter(trigger_event=trigger, is_active=True).order_by("order")
|
|
print(f"Found {steps.count()} active steps.")
|
|
|
|
outputs = []
|
|
for step in steps:
|
|
res = execute_step(step, context)
|
|
outputs.append(res)
|
|
|
|
print(f"================ FINISH WORKFLOW: {workflow_code} ================\n")
|
|
return outputs |