Research-Stack/5-Applications/finance_manager.py
Brandon Schneider 382277ec28 chore: preserve working tree before secure wipe
- Update .gitignore with **/target/ for Rust build artifacts
- Add eval receipts to UniversalBridge.lean (compile-time verification comments)
- Add PCIe Idle-Cycle Compute Harvester to ROADMAP.md
- Clean up deprecated scripts, generated Verilog, and old tools (23 deletions)
- Stage new infrastructure: Xen/Alpine embedded surface, QFOX topology manager
- Stage new probes: boundary activation field, holographic carving
- Stage new applications: finance manager, script roots
- Stage new research spec: PCIe idle-cycle substrate
2026-05-13 17:36:02 -05:00

134 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""
Research Stack Finance Manager (RSFM)
The actual finance program for managing personal_accounts.db and affirm_accounts.db.
"""
import sqlite3
import argparse
import pandas as pd
from pathlib import Path
from datetime import datetime
import sys
# Paths
REPO_ROOT = Path(__file__).resolve().parent.parent
DB_PATH = REPO_ROOT / "shared-data" / "data" / "personal_accounts.db"
AFFIRM_DB_PATH = REPO_ROOT / "shared-data" / "data" / "affirm_accounts.db"
def get_connection(db_path):
if not db_path.exists():
print(f"Error: Database not found at {db_path}")
return None
return sqlite3.connect(db_path)
def list_accounts():
conn = get_connection(DB_PATH)
if not conn: return
print("\n--- Accounts Overview ---")
query = "SELECT merchant, amount, status, type FROM accounts"
df = pd.read_sql_query(query, conn)
if df.empty:
print("No accounts found.")
else:
print(df.to_string(index=False))
conn.close()
def spending_summary(month=None):
conn = get_connection(DB_PATH)
if not conn: return
print("\n--- Spending Summary by Category ---")
# Use rocket_money_transactions for categorized spending
query = "SELECT category, SUM(amount) as total FROM rocket_money_transactions"
if month:
query += f" WHERE date LIKE '{month}%'"
query += " GROUP BY category ORDER BY total DESC"
df = pd.read_sql_query(query, conn)
if df.empty:
print("No transactions found.")
else:
print(df.to_string(index=False))
print(f"\nTotal: {df['total'].sum():.2f}")
conn.close()
def search_transactions(query_term):
conn = get_connection(DB_PATH)
if not conn: return
print(f"\n--- Search Results for '{query_term}' ---")
# Search across main transactions and rocket money
q1 = f"SELECT date, amount, description FROM transactions WHERE description LIKE '%{query_term}%'"
q2 = f"SELECT date, amount, name as description FROM rocket_money_transactions WHERE name LIKE '%{query_term}%' OR custom_name LIKE '%{query_term}%'"
df1 = pd.read_sql_query(q1, conn)
df2 = pd.read_sql_query(q2, conn)
combined = pd.concat([df1, df2]).sort_values(by='date', ascending=False)
if combined.empty:
print("No matches found.")
else:
print(combined.to_string(index=False))
conn.close()
def affirm_summary():
conn = get_connection(AFFIRM_DB_PATH)
if not conn: return
print("\n--- Affirm Loan Summary ---")
# Assuming affirm_accounts.db has a similar structure or check its tables
cursor = conn.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()
if not tables:
print("No data in Affirm database.")
else:
for (table_name,) in tables:
print(f"\nTable: {table_name}")
df = pd.read_sql_query(f"SELECT * FROM {table_name}", conn)
print(df.head().to_string(index=False))
conn.close()
def dashboard():
print("\n" + "="*50)
print(" RESEARCH STACK FINANCIAL DASHBOARD")
print("="*50)
list_accounts()
spending_summary()
print("\n" + "="*50)
def main():
parser = argparse.ArgumentParser(description="Research Stack Finance Manager")
parser.add_argument("--dashboard", action="store_true", help="Show full financial dashboard")
parser.add_argument("--accounts", action="store_true", help="Show accounts overview")
parser.add_argument("--summary", nargs="?", const="all", help="Show spending summary for a month (format: YYYY-MM) or 'all' for total")
parser.add_argument("--search", metavar="TERM", help="Search transactions for a term")
parser.add_argument("--affirm", action="store_true", help="Show Affirm loan status")
args = parser.parse_args()
if len(sys.argv) == 1 or args.dashboard:
dashboard()
if not args.dashboard: sys.exit(0)
if args.accounts:
list_accounts()
if args.summary:
if args.summary == "all":
spending_summary()
else:
spending_summary(args.summary)
if args.search:
search_transactions(args.search)
if args.affirm:
affirm_summary()
if __name__ == "__main__":
main()