# Risk Management Test Data Seeds # Run with: mix run priv/repo/seeds_risk_test_data.exs alias DaProductApp.Repo alias RiskCore.RiskRule alias RiskCore.Transaction alias RiskCore.PosTransaction alias DaProductApp.Merchants.Merchant IO.puts("\n=== Seeding Risk Management Test Data ===\n") # Ensure we have a test merchant merchant = case Repo.get_by(Merchant, merchant_id: "TEST_MERCH_001") do nil -> IO.puts("Creating test merchant...") %Merchant{} |> Merchant.changeset(%{ merchant_id: "TEST_MERCH_001", name: "Test Risk Merchant", category: "Cat A", mcc_code: "5411", # Grocery stores risk_tier: "SME/SMB", status: "active", inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() merchant -> IO.puts("Using existing test merchant: #{merchant.merchant_id}") merchant end # Create Risk Rules IO.puts("\n--- Creating Risk Rules ---") # Rule 1: High Amount Transaction (Category A - Hold) rule1 = case Repo.get_by(RiskRule, name: "High Amount Transaction Test") do nil -> IO.puts("Creating Rule 1: High Amount Transaction (>10,000)") %RiskRule{} |> RiskRule.changeset(%{ name: "High Amount Transaction Test", description: "Hold transactions exceeding 10,000 PKR", category: "Cat A", rule_type: "hold", enabled: true, execution_order: 1, parameters: %{ "max_amount" => 10000.00 }, inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() rule -> rule end # Rule 2: Frequent Small Transactions (Category A - Alert) rule2 = case Repo.get_by(RiskRule, name: "Frequent Small Transactions Test") do nil -> IO.puts("Creating Rule 2: Frequent Small Transactions (<100 PKR, >5 in 1 hour)") %RiskRule{} |> RiskRule.changeset(%{ name: "Frequent Small Transactions Test", description: "Alert on multiple small transactions in short time", category: "Cat A", rule_type: "alert", enabled: true, execution_order: 2, parameters: %{ "max_amount" => 100.00, "min_count" => 5, "time_window_hours" => 1 }, inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() rule -> rule end # Rule 3: International Card Usage (Category B - Alert) rule3 = case Repo.get_by(RiskRule, name: "International Card Test") do nil -> IO.puts("Creating Rule 3: International Card Usage") %RiskRule{} |> RiskRule.changeset(%{ name: "International Card Test", description: "Alert on international card usage", category: "Cat B", rule_type: "alert", enabled: true, execution_order: 3, parameters: %{ "card_type" => "international" }, inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() rule -> rule end IO.puts("\n✓ Created #{Repo.aggregate(RiskRule, :count, :id)} risk rules") # Create QR Test Transactions IO.puts("\n--- Creating QR Test Transactions ---") # QR Transaction 1: Normal transaction (should pass) qr_tx1 = %Transaction{} |> Transaction.changeset(%{ merchant_id: merchant.merchant_id, transaction_amount: Decimal.new("500.00"), transaction_type: "qr_payment", settlement_status: "pending", device_id: "QR_DEVICE_001", transaction_location: "Karachi", inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ QR TX1: Normal 500 PKR - Should PASS (txn_id: #{qr_tx1.id})") # QR Transaction 2: High amount (should trigger Rule 1 - HOLD) qr_tx2 = %Transaction{} |> Transaction.changeset(%{ merchant_id: merchant.merchant_id, transaction_amount: Decimal.new("15000.00"), transaction_type: "qr_payment", settlement_status: "pending", device_id: "QR_DEVICE_001", transaction_location: "Lahore", inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ QR TX2: High Amount 15,000 PKR - Should HOLD (txn_id: #{qr_tx2.id})") # QR Transaction 3: Small transaction (part of frequent small test) qr_tx3 = %Transaction{} |> Transaction.changeset(%{ merchant_id: merchant.merchant_id, transaction_amount: Decimal.new("75.00"), transaction_type: "qr_payment", settlement_status: "pending", device_id: "QR_DEVICE_001", transaction_location: "Karachi", inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ QR TX3: Small Amount 75 PKR (txn_id: #{qr_tx3.id})") # Create POS Test Transactions IO.puts("\n--- Creating POS Test Transactions ---") # POS Transaction 1: Normal domestic card (should pass) pos_tx1 = %PosTransaction{} |> PosTransaction.changeset(%{ merchant_id: merchant.merchant_id, amount: Decimal.new("1200.00"), card_type: "domestic", card_number_masked: "****1234", terminal_id: "POS_TERM_001", status: "success", entry_mode: "chip", response_code: "00", transaction_time: DateTime.utc_now(), inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ POS TX1: Normal Domestic 1,200 PKR - Should PASS (txn_id: #{pos_tx1.id})") # POS Transaction 2: High amount transaction (should trigger Rule 1 - HOLD) pos_tx2 = %PosTransaction{} |> PosTransaction.changeset(%{ merchant_id: merchant.merchant_id, amount: Decimal.new("25000.00"), card_type: "domestic", card_number_masked: "****5678", terminal_id: "POS_TERM_001", status: "success", entry_mode: "chip", response_code: "00", transaction_time: DateTime.utc_now(), inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ POS TX2: High Amount 25,000 PKR - Should HOLD (txn_id: #{pos_tx2.id})") # POS Transaction 3: International card (should trigger Rule 3 - ALERT) pos_tx3 = %PosTransaction{} |> PosTransaction.changeset(%{ merchant_id: merchant.merchant_id, amount: Decimal.new("3500.00"), card_type: "international", card_number_masked: "****9999", terminal_id: "POS_TERM_001", status: "success", entry_mode: "contactless", response_code: "00", country_code: "USA", transaction_time: DateTime.utc_now(), inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ POS TX3: International Card 3,500 PKR - Should ALERT (txn_id: #{pos_tx3.id})") # POS Transaction 4: Small transaction (for frequent small test) pos_tx4 = %PosTransaction{} |> PosTransaction.changeset(%{ merchant_id: merchant.merchant_id, amount: Decimal.new("50.00"), card_type: "domestic", card_number_masked: "****1111", terminal_id: "POS_TERM_001", status: "success", entry_mode: "chip", response_code: "00", transaction_time: DateTime.utc_now(), inserted_at: DateTime.utc_now(), updated_at: DateTime.utc_now() }) |> Repo.insert!() IO.puts("✓ POS TX4: Small Amount 50 PKR (txn_id: #{pos_tx4.id})") IO.puts("\n=== Summary ===") IO.puts("✓ Risk Rules Created: #{Repo.aggregate(RiskRule, :count, :id)}") IO.puts("✓ QR Transactions Created: 3") IO.puts("✓ POS Transactions Created: 4") IO.puts("\n=== Test Expectations ===") IO.puts("QR TX1 (500 PKR): Should PASS all rules") IO.puts("QR TX2 (15,000 PKR): Should trigger HOLD - High Amount") IO.puts("QR TX3 (75 PKR): Might trigger ALERT if multiple similar exist") IO.puts("\nPOS TX1 (1,200 PKR Domestic): Should PASS all rules") IO.puts("POS TX2 (25,000 PKR): Should trigger HOLD - High Amount") IO.puts("POS TX3 (3,500 PKR International): Should trigger ALERT - International Card") IO.puts("POS TX4 (50 PKR): Might trigger ALERT if multiple similar exist") IO.puts("\n=== Next Steps ===") IO.puts("1. Navigate to: http://demo.ctrmv.com:4099/risk-management/rules") IO.puts("2. View the created rules and enable/disable as needed") IO.puts("3. Run risk evaluation on transactions to see which ones trigger rules") IO.puts("4. Check supervisor dashboard: http://demo.ctrmv.com:4099/risk-management/supervisor") IO.puts("\n=== To Evaluate Transactions ===") IO.puts("In IEx console, run:") IO.puts(" alias RiskCore.Context") IO.puts(" alias DaProductApp.Repo") IO.puts(" alias DaProductApp.Schema.Transaction") IO.puts(" alias DaProductApp.Schema.PosTransaction") IO.puts("") IO.puts(" # Evaluate QR transactions") IO.puts(" qr_txns = Repo.all(Transaction) |> Enum.take(5)") IO.puts(" Enum.each(qr_txns, fn tx -> Context.evaluate_transaction_risks(tx, \"QR\") end)") IO.puts("") IO.puts(" # Evaluate POS transactions") IO.puts(" pos_txns = Repo.all(PosTransaction) |> Enum.take(5)") IO.puts(" Enum.each(pos_txns, fn tx -> Context.evaluate_transaction_risks(tx, \"POS\") end)") IO.puts("\n✅ Test data seeding completed!\n")