Bankbot / backend /app /scripts /seed_demo.py
mohsin-devs's picture
Deploy to HF Space
7a30d73
Raw
History Blame Contribute Delete
16.4 kB
"""
Demo seed script β€” creates a polished demo account (alex@bankbot.dev)
with realistic financial data: transactions, goals, investments,
subscriptions, notifications, and a fraud alert.
Run: python app/scripts/seed_demo.py
"""
import os
import sys
import uuid
import random
from datetime import datetime, timedelta
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
import bcrypt as _bcrypt
from app.database.database import SessionLocal, engine
from app.database.models import (
Base, User, Account, Transaction, Subscription,
Goal, Investment, Notification, FraudLog
)
Base.metadata.create_all(bind=engine)
DEMO_EMAIL = "alex@bankbot.dev"
DEMO_PASSWORD = "BankBot2026!"
DEMO_NAME = "Alex Doe"
def hash_pw(pw: str) -> str:
return _bcrypt.hashpw(pw.encode(), _bcrypt.gensalt(rounds=12)).decode()
def uid() -> str:
return str(uuid.uuid4())
def seed():
db = SessionLocal()
try:
# ── Remove existing demo user ────────────────────────────────────────
existing = db.query(User).filter(User.email == DEMO_EMAIL).first()
if existing:
db.delete(existing)
db.commit()
print(f"Removed existing demo user: {DEMO_EMAIL}")
# ── Create demo user ─────────────────────────────────────────────────
user = User(
id=uid(),
email=DEMO_EMAIL,
password_hash=hash_pw(DEMO_PASSWORD),
profile_data={
"name": DEMO_NAME,
"phone": "+1 (555) 012-3456",
"avatar": "AD",
"member_since": "2023-01-15",
"plan": "Premium",
},
financial_personality="Balanced Investor",
ai_personalization_settings={
"risk_tolerance": "moderate",
"investment_horizon": "long_term",
"notifications": "all",
"ai_tone": "analytical",
},
)
db.add(user)
db.flush()
print(f"Created demo user: {DEMO_EMAIL}")
# ── Accounts ─────────────────────────────────────────────────────────
checking = Account(id=uid(), user_id=user.id, type="checking",
balance=12_847.32, currency="USD", status="active")
savings = Account(id=uid(), user_id=user.id, type="savings",
balance=28_450.00, currency="USD", status="active")
invest = Account(id=uid(), user_id=user.id, type="investment",
balance=18_340.50, currency="USD", status="active")
db.add_all([checking, savings, invest])
db.flush()
print("Created 3 accounts (checking $12,847 | savings $28,450 | investment $18,340)")
# ── Transactions β€” 6 months of realistic data ─────────────────────────
now = datetime.utcnow()
merchants = [
# (name, category, type, amount_range)
("Salary Deposit", "Income", "credit", (4800, 5200)),
("Freelance Payment", "Income", "credit", (800, 2000)),
("Whole Foods", "Groceries", "debit", (45, 180)),
("Trader Joe's", "Groceries", "debit", (30, 120)),
("Netflix", "Entertainment", "debit", (15, 16)),
("Spotify", "Entertainment", "debit", (9, 10)),
("Amazon", "Shopping", "debit", (25, 250)),
("Apple Store", "Tech", "debit", (10, 200)),
("Uber", "Transport", "debit", (8, 45)),
("Shell Gas", "Transport", "debit", (40, 80)),
("Starbucks", "Food", "debit", (5, 18)),
("Chipotle", "Food", "debit", (10, 25)),
("Planet Fitness", "Health", "debit", (24, 25)),
("CVS Pharmacy", "Health", "debit", (12, 60)),
("Con Edison", "Utilities", "debit", (80, 140)),
("Verizon", "Utilities", "debit", (85, 90)),
("Rent Payment", "Housing", "debit", (1950, 1950)),
("Dividend Income", "Investment", "credit", (120, 350)),
("Restaurant", "Food", "debit", (30, 90)),
("Target", "Shopping", "debit", (40, 150)),
]
txns = []
for month_offset in range(6):
month_start = (now.replace(day=1) - timedelta(days=month_offset * 30))
# Salary on 1st
txns.append(Transaction(
id=uid(), account_id=checking.id,
amount=random.uniform(4800, 5200), type="credit",
category="Income", merchant="Salary Deposit",
timestamp=month_start + timedelta(hours=9),
tags=["recurring", "income"],
))
# Rent on 3rd
txns.append(Transaction(
id=uid(), account_id=checking.id,
amount=1950.00, type="debit",
category="Housing", merchant="Rent Payment",
timestamp=month_start + timedelta(days=2, hours=10),
tags=["recurring", "housing"],
))
# Random daily transactions
for _ in range(random.randint(18, 28)):
m = random.choice(merchants[2:]) # skip salary/rent
days_offset = random.randint(0, 28)
hours_offset = random.randint(7, 22)
txns.append(Transaction(
id=uid(), account_id=checking.id,
amount=round(random.uniform(*m[3]), 2),
type=m[2], category=m[1], merchant=m[0],
timestamp=month_start + timedelta(days=days_offset, hours=hours_offset),
tags=[m[1].lower()],
))
# One suspicious transaction for fraud demo
fraud_txn = Transaction(
id=uid(), account_id=checking.id,
amount=847.00, type="debit",
category="Shopping", merchant="Tech Store NYC",
timestamp=now - timedelta(hours=2),
tags=["flagged"],
spending_emotion_label="impulsive",
)
txns.append(fraud_txn)
db.add_all(txns)
db.flush()
print(f"Created {len(txns)} transactions across 6 months")
# ── Fraud log for the suspicious transaction ──────────────────────────
fraud_log = FraudLog(
id=uid(),
transaction_id=fraud_txn.id,
risk_score=0.78,
suspicious_activity_details=(
"Transaction amount ($847.00) is 3.2x above historical average. "
"Location anomaly: merchant in NYC, usual activity in Brooklyn. "
"Placed at 11:47 PM β€” outside normal spending hours."
),
status="pending",
)
db.add(fraud_log)
print("Created fraud alert for demo transaction")
# ── Goals ─────────────────────────────────────────────────────────────
goals = [
Goal(id=uid(), user_id=user.id, title="Emergency Fund",
target_amount=18_000, current_amount=14_200,
target_date=now + timedelta(days=90),
ai_generated_plan={"monthly_contribution": 1267, "months_remaining": 3}),
Goal(id=uid(), user_id=user.id, title="Europe Vacation",
target_amount=5_000, current_amount=2_800,
target_date=now + timedelta(days=180),
ai_generated_plan={"monthly_contribution": 367, "months_remaining": 6}),
Goal(id=uid(), user_id=user.id, title="MacBook Pro",
target_amount=2_500, current_amount=1_900,
target_date=now + timedelta(days=45),
ai_generated_plan={"monthly_contribution": 300, "months_remaining": 2}),
Goal(id=uid(), user_id=user.id, title="Down Payment Fund",
target_amount=80_000, current_amount=28_450,
target_date=now + timedelta(days=730),
ai_generated_plan={"monthly_contribution": 2148, "months_remaining": 24}),
]
db.add_all(goals)
print(f"Created {len(goals)} financial goals")
# ── Investments ───────────────────────────────────────────────────────
investments = [
Investment(id=uid(), user_id=user.id, asset_name="S&P 500 Index Fund",
type="mutual_fund", amount_invested=8_000, current_value=9_840,
portfolio_allocation=53.6,
ai_risk_analysis={"risk": "moderate", "expected_return": "8-10%", "recommendation": "hold"}),
Investment(id=uid(), user_id=user.id, asset_name="Apple Inc (AAPL)",
type="stock", amount_invested=3_000, current_value=3_720,
portfolio_allocation=20.3,
ai_risk_analysis={"risk": "moderate-high", "expected_return": "12-15%", "recommendation": "hold"}),
Investment(id=uid(), user_id=user.id, asset_name="Bitcoin (BTC)",
type="crypto", amount_invested=2_500, current_value=2_980,
portfolio_allocation=16.2,
ai_risk_analysis={"risk": "high", "expected_return": "variable", "recommendation": "reduce_exposure"}),
Investment(id=uid(), user_id=user.id, asset_name="US Treasury Bonds",
type="bond", amount_invested=1_800, current_value=1_800,
portfolio_allocation=9.8,
ai_risk_analysis={"risk": "low", "expected_return": "4.5%", "recommendation": "hold"}),
]
db.add_all(investments)
print(f"Created {len(investments)} investments (total value: ${sum(i.current_value for i in investments):,.0f})")
# ── Subscriptions ─────────────────────────────────────────────────────
subscriptions = [
Subscription(id=uid(), user_id=user.id, merchant="Netflix",
amount=15.99, billing_cycle="monthly", active=True,
ai_usage_detection={"last_used": "2 days ago", "usage_frequency": "high"}),
Subscription(id=uid(), user_id=user.id, merchant="Spotify",
amount=9.99, billing_cycle="monthly", active=True,
ai_usage_detection={"last_used": "today", "usage_frequency": "daily"}),
Subscription(id=uid(), user_id=user.id, merchant="Adobe Creative Cloud",
amount=54.99, billing_cycle="monthly", active=True,
ai_usage_detection={"last_used": "45 days ago", "usage_frequency": "low"}),
Subscription(id=uid(), user_id=user.id, merchant="Planet Fitness",
amount=24.99, billing_cycle="monthly", active=True,
ai_usage_detection={"last_used": "1 week ago", "usage_frequency": "medium"}),
Subscription(id=uid(), user_id=user.id, merchant="iCloud Storage",
amount=2.99, billing_cycle="monthly", active=True,
ai_usage_detection={"last_used": "today", "usage_frequency": "daily"}),
Subscription(id=uid(), user_id=user.id, merchant="LinkedIn Premium",
amount=39.99, billing_cycle="monthly", active=True,
ai_usage_detection={"last_used": "60 days ago", "usage_frequency": "very_low"}),
]
db.add_all(subscriptions)
monthly_sub_cost = sum(s.amount for s in subscriptions)
print(f"Created {len(subscriptions)} subscriptions (${monthly_sub_cost:.2f}/month)")
# ── Notifications ─────────────────────────────────────────────────────
notifications = [
Notification(id=uid(), user_id=user.id,
title="🚨 Unusual Transaction Detected",
message="A charge of $847.00 at 'Tech Store NYC' was flagged. "
"This is 3.2x your average transaction and occurred at 11:47 PM. "
"Please review and confirm.",
type="alert", read_status=False,
created_at=now - timedelta(hours=2)),
Notification(id=uid(), user_id=user.id,
title="πŸ’‘ AI Weekly Insight",
message="Your savings rate this month is 38.4% β€” 18% above the national average. "
"At this pace, you'll reach your Emergency Fund goal in 3 months.",
type="insight", read_status=False,
created_at=now - timedelta(hours=6)),
Notification(id=uid(), user_id=user.id,
title="⚠️ Budget Alert: Shopping",
message="You've spent $847 in Shopping this month β€” 141% of your $600 budget. "
"Consider pausing non-essential purchases for the rest of the month.",
type="warning", read_status=False,
created_at=now - timedelta(hours=8)),
Notification(id=uid(), user_id=user.id,
title="🎯 Goal Milestone Reached",
message="Your Emergency Fund is now 78.9% funded ($14,200 of $18,000). "
"You're on track to complete it by August 2026.",
type="insight", read_status=True,
created_at=now - timedelta(days=1)),
Notification(id=uid(), user_id=user.id,
title="πŸ“Š Monthly Report Ready",
message="Your May 2026 financial report is ready. "
"Net savings: $1,847. Top category: Housing (38%). "
"Health score improved by 3 points to 82/100.",
type="insight", read_status=True,
created_at=now - timedelta(days=2)),
Notification(id=uid(), user_id=user.id,
title="πŸ’° Subscription Optimization",
message="AI detected 2 underused subscriptions: Adobe CC ($54.99/mo, last used 45 days ago) "
"and LinkedIn Premium ($39.99/mo, last used 60 days ago). "
"Cancelling both saves $1,139.76/year.",
type="warning", read_status=True,
created_at=now - timedelta(days=3)),
]
db.add_all(notifications)
print(f"Created {len(notifications)} notifications ({sum(1 for n in notifications if not n.read_status)} unread)")
db.commit()
print("\n" + "="*60)
print("DEMO ACCOUNT SEEDED SUCCESSFULLY")
print("="*60)
print(f" Email: {DEMO_EMAIL}")
print(f" Password: {DEMO_PASSWORD}")
print(f" Balance: ${checking.balance + savings.balance + invest.balance:,.2f} total")
print(f" Score: 82/100 (estimated)")
print(f" Fraud: 1 pending alert")
print("="*60)
except Exception as e:
db.rollback()
print(f"SEED FAILED: {e}")
raise
finally:
db.close()
if __name__ == "__main__":
seed()