Initial release v1.1.0
- Complete MVP for tracking Fidelity brokerage account performance - Transaction import from CSV with deduplication - Automatic FIFO position tracking with options support - Real-time P&L calculations with market data caching - Dashboard with timeframe filtering (30/90/180 days, 1 year, YTD, all time) - Docker-based deployment with PostgreSQL backend - React/TypeScript frontend with TailwindCSS - FastAPI backend with SQLAlchemy ORM Features: - Multi-account support - Import via CSV upload or filesystem - Open and closed position tracking - Balance history charting - Performance analytics and metrics - Top trades analysis - Responsive UI design Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
157
apply_patches.py
Executable file
157
apply_patches.py
Executable file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Apply patches for rate limiting fix.
|
||||
This Python script works across all platforms.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def backup_file(filepath):
|
||||
"""Create backup of file."""
|
||||
backup_path = f"{filepath}.backup"
|
||||
shutil.copy2(filepath, backup_path)
|
||||
print(f"✓ Backed up {filepath} to {backup_path}")
|
||||
return backup_path
|
||||
|
||||
|
||||
def patch_main_py():
|
||||
"""Patch backend/app/main.py to use analytics_v2."""
|
||||
filepath = Path("backend/app/main.py")
|
||||
|
||||
if not filepath.exists():
|
||||
print(f"❌ Error: {filepath} not found")
|
||||
return False
|
||||
|
||||
print(f"\n[1/2] Patching {filepath}...")
|
||||
|
||||
# Backup
|
||||
backup_file(filepath)
|
||||
|
||||
# Read file
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check if already patched
|
||||
if 'analytics_v2 as analytics' in content or 'import analytics_v2' in content:
|
||||
print("✓ Backend already patched (analytics_v2 found)")
|
||||
return True
|
||||
|
||||
# Apply patch
|
||||
old_import = "from app.api.endpoints import accounts, transactions, positions, analytics"
|
||||
new_import = "from app.api.endpoints import accounts, transactions, positions, analytics_v2 as analytics"
|
||||
|
||||
if old_import in content:
|
||||
content = content.replace(old_import, new_import)
|
||||
|
||||
# Write back
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print("✓ Backend patched successfully")
|
||||
return True
|
||||
else:
|
||||
print("❌ Could not find expected import line")
|
||||
print("\nLooking for:")
|
||||
print(f" {old_import}")
|
||||
print("\nPlease manually edit backend/app/main.py")
|
||||
return False
|
||||
|
||||
|
||||
def patch_app_tsx():
|
||||
"""Patch frontend/src/App.tsx to use DashboardV2."""
|
||||
filepath = Path("frontend/src/App.tsx")
|
||||
|
||||
if not filepath.exists():
|
||||
print(f"❌ Error: {filepath} not found")
|
||||
return False
|
||||
|
||||
print(f"\n[2/2] Patching {filepath}...")
|
||||
|
||||
# Backup
|
||||
backup_file(filepath)
|
||||
|
||||
# Read file
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check if already patched
|
||||
if 'DashboardV2' in content or "components/DashboardV2" in content:
|
||||
print("✓ Frontend already patched (DashboardV2 found)")
|
||||
return True
|
||||
|
||||
# Apply patch - handle both single and double quotes
|
||||
old_import1 = "import Dashboard from './components/Dashboard'"
|
||||
new_import1 = "import Dashboard from './components/DashboardV2'"
|
||||
old_import2 = 'import Dashboard from "./components/Dashboard"'
|
||||
new_import2 = 'import Dashboard from "./components/DashboardV2"'
|
||||
|
||||
changed = False
|
||||
if old_import1 in content:
|
||||
content = content.replace(old_import1, new_import1)
|
||||
changed = True
|
||||
if old_import2 in content:
|
||||
content = content.replace(old_import2, new_import2)
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
# Write back
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
print("✓ Frontend patched successfully")
|
||||
return True
|
||||
else:
|
||||
print("❌ Could not find expected import line")
|
||||
print("\nLooking for:")
|
||||
print(f" {old_import1}")
|
||||
print(f" or {old_import2}")
|
||||
print("\nPlease manually edit frontend/src/App.tsx")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("Applying Rate Limiting Fix Patches (Python)")
|
||||
print("=" * 60)
|
||||
|
||||
# Check we're in the right directory
|
||||
if not Path("docker-compose.yml").exists():
|
||||
print("\n❌ Error: docker-compose.yml not found")
|
||||
print("Please run this script from the fidelity project directory")
|
||||
sys.exit(1)
|
||||
|
||||
# Apply patches
|
||||
backend_ok = patch_main_py()
|
||||
frontend_ok = patch_app_tsx()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
|
||||
if backend_ok and frontend_ok:
|
||||
print("✅ All patches applied successfully!")
|
||||
print("=" * 60)
|
||||
print("\nNext steps:")
|
||||
print("")
|
||||
print("1. Rebuild containers:")
|
||||
print(" docker compose down")
|
||||
print(" docker compose build --no-cache backend frontend")
|
||||
print(" docker compose up -d")
|
||||
print("")
|
||||
print("2. Run migration:")
|
||||
print(" sleep 30")
|
||||
print(" docker compose exec backend alembic upgrade head")
|
||||
print("")
|
||||
print("3. Test:")
|
||||
print(" curl http://localhost:8000/api/analytics/overview/1?refresh_prices=false")
|
||||
print("")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("⚠️ Some patches failed - see manual instructions above")
|
||||
print("=" * 60)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user