# Demo script to showcase Action History feature in Risk Management # Run with: mix run demo_action_history.exs alias PlatformCore.Repo alias RiskCore.Context alias RiskCore.RiskRuleHit import Ecto.Query IO.puts("\n" <> String.duplicate("=", 80)) IO.puts("šŸ“‹ Action History Demo - Risk Management Dashboard") IO.puts(String.duplicate("=", 80) <> "\n") # Step 1: Find a recent risk rule hit to work with IO.puts("Step 1: Finding a recent risk rule hit...") recent_hit = Repo.one( from h in RiskRuleHit, where: h.status == "Hold", order_by: [desc: h.inserted_at], limit: 1, preload: :rule ) case recent_hit do nil -> IO.puts("āŒ No risk hits found in Hold status.") IO.puts("\nšŸ’” Tip: Run the seed script first:") IO.puts(" mix run priv/repo/seed_risk_transactions.exs\n") hit -> IO.puts("āœ… Found Risk Hit ID: #{hit.id}") IO.puts(" Transaction Type: #{hit.transaction_type}") IO.puts(" Merchant ID: #{hit.merchant_id}") IO.puts(" Status: #{hit.status}") IO.puts(" Rule: #{hit.rule.name}") # Step 2: Show initial action history IO.puts("\n" <> String.duplicate("-", 80)) IO.puts("Step 2: Checking initial action history...") initial_history = Context.get_hit_action_history(hit.id) if length(initial_history) > 0 do IO.puts("āœ… Found #{length(initial_history)} action(s) in history:\n") Enum.each(initial_history, fn action -> timestamp_str = if action.timestamp do Calendar.strftime(action.timestamp, "%Y-%m-%d %H:%M:%S") else "N/A" end IO.puts(" šŸ“ #{timestamp_str}") IO.puts(" Action: #{action.action}") IO.puts(" Status: #{action.from_status || "N/A"} → #{action.to_status || "N/A"}") IO.puts(" Supervisor: #{action.supervisor_name}") if action.notes, do: IO.puts(" Notes: #{action.notes}") IO.puts("") end) else IO.puts("āš ļø No action history found (legacy data)") end # Step 3: Simulate supervisor action - Request Documents IO.puts(String.duplicate("-", 80)) IO.puts("Step 3: Simulating supervisor action - Request Documents...") case Context.update_risk_rule_hit_action(hit.id, 1, "Request Docs", "Please provide transaction receipt and customer ID verification") do {:ok, updated_hit} -> IO.puts("āœ… Action recorded successfully!") IO.puts(" New Status: #{updated_hit.status}") IO.puts(" Action Taken: #{updated_hit.action_taken}") # Step 4: Show updated action history IO.puts("\n" <> String.duplicate("-", 80)) IO.puts("Step 4: Viewing updated action history...") updated_history = Context.get_hit_action_history(hit.id) IO.puts("āœ… Now showing #{length(updated_history)} action(s) in history:\n") Enum.each(updated_history, fn action -> timestamp_str = if action.timestamp do Calendar.strftime(action.timestamp, "%Y-%m-%d %H:%M:%S") else "N/A" end IO.puts(" šŸ“ #{timestamp_str}") IO.puts(" Action: #{action.action}") IO.puts(" Status: #{action.from_status || "N/A"} → #{action.to_status || "N/A"}") IO.puts(" Supervisor: #{action.supervisor_name}") if action.notes, do: IO.puts(" Notes: #{action.notes}") IO.puts("") end) # Step 5: Simulate another action - Reject IO.puts(String.duplicate("-", 80)) IO.puts("Step 5: Simulating another supervisor action - Reject...") case Context.update_risk_rule_hit_action(updated_hit.id, 2, "Reject", "Transaction flagged as fraudulent after document review") do {:ok, final_hit} -> IO.puts("āœ… Rejection recorded successfully!") IO.puts(" Final Status: #{final_hit.status}") # Final action history IO.puts("\n" <> String.duplicate("-", 80)) IO.puts("Step 6: Final action history timeline...") final_history = Context.get_hit_action_history(final_hit.id) IO.puts("āœ… Complete timeline with #{length(final_history)} action(s):\n") Enum.with_index(final_history, 1) |> Enum.each(fn {action, idx} -> timestamp_str = if action.timestamp do Calendar.strftime(action.timestamp, "%Y-%m-%d %H:%M:%S") else "N/A" end IO.puts(" #{idx}. #{timestamp_str}") IO.puts(" Action: #{action.action}") IO.puts(" Status Change: #{action.from_status || "N/A"} → #{action.to_status || "N/A"}") IO.puts(" Supervisor: #{action.supervisor_name}") if action.notes, do: IO.puts(" Notes: #{action.notes}") IO.puts("") end) IO.puts(String.duplicate("=", 80)) IO.puts("āœ… Demo Complete! Action history is now visible in the Risk Dashboard modal.") IO.puts(String.duplicate("=", 80) <> "\n") {:error, reason} -> IO.puts("āŒ Failed to reject: #{inspect(reason)}") end {:error, reason} -> IO.puts("āŒ Failed to update: #{inspect(reason)}") end end