Initial commit: WealthWise financial analytics platform

This commit is contained in:
2026-02-14 21:16:57 +05:30
commit b8588df583
171 changed files with 29048 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
"""Initialize database tables.
This script creates all database tables defined in the models.
Run this before starting the application for the first time.
"""
import asyncio
from sqlalchemy.ext.asyncio import create_async_engine
from app.core.config import get_settings
from app.models.base import BaseModel
settings = get_settings()
async def init_db():
"""Create all database tables."""
engine = create_async_engine(settings.DATABASE_URL, echo=True)
async with engine.begin() as conn:
await conn.run_sync(BaseModel.metadata.create_all)
await engine.dispose()
print("Database tables created successfully!")
if __name__ == "__main__":
asyncio.run(init_db())

View File

@@ -0,0 +1,57 @@
#!/bin/bash
# WealthWise Database Migration Script
# This script initializes Alembic and creates the initial migration
echo "Setting up Alembic migrations for WealthWise..."
# Check if alembic is installed
if ! command -v alembic &> /dev/null; then
echo "Installing alembic..."
pip install alembic
fi
# Initialize Alembic if not already initialized
if [ ! -d "alembic" ]; then
echo "Initializing Alembic..."
alembic init alembic
# Update alembic.ini with database URL
sed -i '' 's|sqlalchemy.url = driver://user:pass@localhost/dbname|sqlalchemy.url = postgresql://postgres:postgres@localhost:5432/wealthwise|' alembic/alembic.ini 2>/dev/null || sed -i 's|sqlalchemy.url = driver://user:pass@localhost/dbname|sqlalchemy.url = postgresql://postgres:postgres@localhost:5432/wealthwise|' alembic/alembic.ini
echo "Alembic initialized successfully!"
else
echo "Alembic already initialized."
fi
echo ""
echo "Next steps:"
echo "1. Update alembic/env.py to import your models (see instructions below)"
echo "2. Run: alembic revision --autogenerate -m 'Initial migration'"
echo "3. Run: alembic upgrade head"
echo ""
echo "=== alembic/env.py Configuration ==="
echo "Add these imports to alembic/env.py:"
echo ""
echo "import asyncio"
echo "from sqlalchemy.ext.asyncio import AsyncEngine"
echo "from app.models import User, Portfolio, Transaction"
echo "from app.models.base import BaseModel"
echo ""
echo "Then update run_migrations_online() to use async engine:"
echo ""
echo "def do_run_migrations(connection):"
echo " context.configure(connection=connection, target_metadata=BaseModel.metadata)"
echo " with context.begin_transaction():"
echo " context.run_migrations()"
echo ""
echo "async def run_migrations_online():"
echo " connectable = AsyncEngine(create_async_engine(config.get_main_option('sqlalchemy.url')))"
echo " async with connectable.connect() as connection:"
echo " await connection.run_sync(do_run_migrations)"
echo " await connectable.dispose()"
echo ""
echo "if context.is_offline_mode():"
echo " run_migrations_offline()"
echo "else:"
echo " asyncio.run(run_migrations_online())"

195
backend/scripts/seed_db.py Normal file
View File

@@ -0,0 +1,195 @@
"""Database seeding script for WealthWise.
This script populates the database with sample data for development and testing.
"""
import asyncio
from datetime import date, timedelta
from decimal import Decimal
from uuid import uuid4
from sqlalchemy import select
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.db import AsyncSessionLocal, engine
from app.core.security import get_password_hash
from app.models import Portfolio, Transaction, User
from app.models.transaction import TransactionType
async def seed_database():
"""Seed the database with sample data."""
print("Starting database seeding...")
async with AsyncSessionLocal() as session:
# Check if demo user already exists
result = await session.execute(
select(User).where(User.email == "demo@wealthwise.app")
)
existing_user = result.scalar_one_or_none()
if existing_user:
print("Demo user already exists. Skipping seeding.")
return
# Create demo user
print("Creating demo user...")
demo_user = User(
id=uuid4(),
email="demo@wealthwise.app",
hashed_password=get_password_hash("password123"),
is_active=True,
is_superuser=False,
)
session.add(demo_user)
await session.flush() # Flush to get the user ID
print(f"Created user: {demo_user.email} (ID: {demo_user.id})")
# Create portfolio
print("Creating portfolio...")
portfolio = Portfolio(
id=uuid4(),
user_id=demo_user.id,
name="Main Investment",
description="Primary investment portfolio for tracking stocks, mutual funds, and other assets.",
)
session.add(portfolio)
await session.flush()
print(f"Created portfolio: {portfolio.name} (ID: {portfolio.id})")
# Create sample transactions
print("Creating transactions...")
transactions = [
# Income transactions
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("75000.00"),
transaction_type=TransactionType.INCOME,
transaction_date=date.today() - timedelta(days=30),
description="Monthly Salary",
category="Salary",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("2500.00"),
transaction_type=TransactionType.INCOME,
transaction_date=date.today() - timedelta(days=25),
description="Freelance Project Payment",
category="Freelance",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("1200.00"),
transaction_type=TransactionType.INCOME,
transaction_date=date.today() - timedelta(days=20),
description="Stock Dividend - TCS",
category="Dividend",
),
# Expense transactions
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("25000.00"),
transaction_type=TransactionType.EXPENSE,
transaction_date=date.today() - timedelta(days=28),
description="Monthly Rent",
category="Housing",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("8000.00"),
transaction_type=TransactionType.EXPENSE,
transaction_date=date.today() - timedelta(days=26),
description="Grocery Shopping - BigBasket",
category="Groceries",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("3500.00"),
transaction_type=TransactionType.EXPENSE,
transaction_date=date.today() - timedelta(days=22),
description="Electricity & Internet Bill",
category="Utilities",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("5000.00"),
transaction_type=TransactionType.EXPENSE,
transaction_date=date.today() - timedelta(days=18),
description="Dining Out & Entertainment",
category="Entertainment",
),
# Investment transactions
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("10000.00"),
transaction_type=TransactionType.TRANSFER,
transaction_date=date.today() - timedelta(days=24),
description="Stock Purchase - Infosys",
category="Investment",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("5000.00"),
transaction_type=TransactionType.TRANSFER,
transaction_date=date.today() - timedelta(days=21),
description="Mutual Fund SIP - SBI Bluechip",
category="Investment",
),
Transaction(
id=uuid4(),
portfolio_id=portfolio.id,
amount=Decimal("3000.00"),
transaction_type=TransactionType.TRANSFER,
transaction_date=date.today() - timedelta(days=15),
description="Crypto Purchase - Bitcoin",
category="Investment",
),
]
for transaction in transactions:
session.add(transaction)
await session.commit()
print(f"Created {len(transactions)} transactions")
# Calculate summary
income_total = sum(t.amount for t in transactions if t.transaction_type == TransactionType.INCOME)
expense_total = sum(t.amount for t in transactions if t.transaction_type == TransactionType.EXPENSE)
transfer_total = sum(t.amount for t in transactions if t.transaction_type == TransactionType.TRANSFER)
print("\n" + "="*50)
print("SEEDING COMPLETE!")
print("="*50)
print(f"User: {demo_user.email}")
print(f"Password: password123")
print(f"Portfolio: {portfolio.name}")
print(f"\nTransaction Summary:")
print(f" Total Income: ₹{income_total:,.2f}")
print(f" Total Expenses: ₹{expense_total:,.2f}")
print(f" Total Investments: ₹{transfer_total:,.2f}")
print(f" Net Cash Flow: ₹{(income_total - expense_total):,.2f}")
print("="*50)
async def main():
"""Main entry point for seeding."""
try:
await seed_database()
except Exception as e:
print(f"Error seeding database: {e}")
raise
finally:
await engine.dispose()
if __name__ == "__main__":
asyncio.run(main())