-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase.py
More file actions
136 lines (120 loc) · 4.97 KB
/
Copy pathdatabase.py
File metadata and controls
136 lines (120 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import os
import json
import pandas as pd
from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime
from sqlalchemy.orm import declarative_base, sessionmaker
from datetime import datetime
DATABASE_URL = "sqlite:///portfolio.db"
engine = create_engine(DATABASE_URL, echo=False)
SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()
class Holding(Base):
__tablename__ = "holdings"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
ticker = Column(String, default="")
side = Column(String, nullable=False)
category = Column(String, nullable=False)
currency = Column(String, default="USD")
quantity = Column(Float, default=1.0)
cost_basis = Column(Float, default=0.0)
current_value = Column(Float, default=0.0)
date_added = Column(String)
notes = Column(String, default="")
class Snapshot(Base):
__tablename__ = "snapshots"
id = Column(Integer, primary_key=True, index=True)
date = Column(String, nullable=False)
net_worth = Column(Float, default=0.0)
total_assets = Column(Float, default=0.0)
total_liabilities = Column(Float, default=0.0)
Base.metadata.create_all(bind=engine)
def migrate_from_json():
"""Migrate data from legacy JSON to SQLite if the database is empty."""
session = SessionLocal()
# Check if empty
if session.query(Holding).count() == 0 and os.path.exists("portfolio_data.json"):
try:
with open("portfolio_data.json") as f:
data = json.load(f)
for item in data:
h = Holding(
id=item.get("id"),
name=item.get("Name"),
ticker=item.get("Ticker", ""),
side=item.get("Side"),
category=item.get("Category"),
currency=item.get("Currency", "USD"),
quantity=float(item.get("Quantity", 1.0)),
cost_basis=float(item.get("Cost Basis", 0.0)),
current_value=float(item.get("Current Value", 0.0)),
date_added=item.get("Date Added", ""),
notes=item.get("Notes", "")
)
session.add(h)
session.commit()
print("Successfully migrated holdings to SQLite.")
except Exception as e:
print("Migration of holdings failed:", e)
session.rollback()
if session.query(Snapshot).count() == 0 and os.path.exists("snapshots.json"):
try:
with open("snapshots.json") as f:
snaps = json.load(f)
for s in snaps:
snap = Snapshot(
date=s.get("date"),
net_worth=float(s.get("net_worth", 0)),
total_assets=float(s.get("total_assets", 0)),
total_liabilities=float(s.get("total_liabilities", 0))
)
session.add(snap)
session.commit()
print("Successfully migrated snapshots to SQLite.")
except Exception as e:
print("Migration of snapshots failed:", e)
session.rollback()
session.close()
# Run migration on load
migrate_from_json()
def get_holdings_df():
"""Load holdings into the legacy pandas format."""
df = pd.read_sql("SELECT * FROM holdings", con=engine)
if not df.empty:
# Standardize column names back to original for compatibility
rename_map = {
"name": "Name", "ticker": "Ticker", "side": "Side",
"category": "Category", "currency": "Currency",
"quantity": "Quantity", "cost_basis": "Cost Basis",
"current_value": "Current Value", "date_added": "Date Added",
"notes": "Notes"
}
df.rename(columns=rename_map, inplace=True)
return df
def save_holdings_df(df: pd.DataFrame):
"""Save the pandas dataframe to the holdings table."""
if df.empty:
with engine.begin() as conn:
conn.execute(Holding.__table__.delete())
return
df_sql = df.copy()
rename_map = {
"Name": "name", "Ticker": "ticker", "Side": "side",
"Category": "category", "Currency": "currency",
"Quantity": "quantity", "Cost Basis": "cost_basis",
"Current Value": "current_value", "Date Added": "date_added",
"Notes": "notes"
}
df_sql.rename(columns=rename_map, inplace=True)
df_sql.to_sql("holdings", con=engine, if_exists="replace", index=False)
def get_snapshots_df():
df = pd.read_sql("SELECT * FROM snapshots ORDER BY date ASC", con=engine)
if not df.empty:
df["date"] = pd.to_datetime(df["date"])
return df
def save_snapshot(date_str, net_worth, total_assets, total_liabilities):
session = SessionLocal()
snap = Snapshot(date=date_str, net_worth=net_worth, total_assets=total_assets, total_liabilities=total_liabilities)
session.add(snap)
session.commit()
session.close()