feat: mo_data.py unified read layer (DB-first, JSON fallback) + cash_log table + batch JSON→DB migration (16 files)

This commit is contained in:
知微
2026-07-01 23:45:30 +08:00
parent 864d924012
commit 6305204c7a
52 changed files with 16351 additions and 11643 deletions
+54
View File
@@ -263,6 +263,20 @@ def init_all_tables(conn: sqlite3.Connection):
updated_at TEXT
);
-- 现金变更日志(每次买卖/出入金记录)
CREATE TABLE IF NOT EXISTS cash_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL DEFAULT (datetime('now','localtime')),
cash_before REAL, -- 变更前可用现金
cash_after REAL, -- 变更后可用现金
frozen_before REAL, -- 变更前冻结资金
frozen_after REAL, -- 变更后冻结资金
change_amount REAL, -- 现金变动额(正=入金/卖股,负=出金/买股)
source TEXT NOT NULL, -- 来源: screenshot/manual/import_xls/trade
note TEXT, -- 备注: 例如 "卖出法拉电子 200股"
verified INTEGER DEFAULT 0 -- 是否已验证(0=未验证,1=Dad确认)
);
-- 建议时间线(decisions.json advice_timeline[]
CREATE TABLE IF NOT EXISTS advice_timeline (
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -371,6 +385,20 @@ def init_all_tables(conn: sqlite3.Connection):
except sqlite3.OperationalError:
pass
# cash_log migration (2026-07-01)
try:
conn.execute("ALTER TABLE cash_log ADD COLUMN frozen_before REAL")
except sqlite3.OperationalError:
pass
try:
conn.execute("ALTER TABLE cash_log ADD COLUMN frozen_after REAL")
except sqlite3.OperationalError:
pass
try:
conn.execute("ALTER TABLE cash_log ADD COLUMN verified INTEGER DEFAULT 0")
except sqlite3.OperationalError:
pass
# ── 币种约束迁移(2026-06-30)────────────────────────────────
_currency_migrations = [
("holdings", ["price REAL", "market_value REAL", "change_pct REAL",
@@ -1041,3 +1069,29 @@ def write_watchlist_stock(conn, stock: dict) -> tuple[bool, str]:
return True, f"自选 {stock.get('code')} 已写入"
except sqlite3.IntegrityError as e:
return False, f"约束: {e}"
def write_cash_log(conn, data: dict) -> tuple[bool, str]:
"""记录现金变更(替代手动改 portfolio.json cash 字段)"""
try:
conn.execute("""
INSERT INTO cash_log (cash_before, cash_after, frozen_before, frozen_after,
change_amount, source, note)
VALUES (?,?,?,?,?,?,?)
""", (
data.get('cash_before'), data.get('cash_after'),
data.get('frozen_before'), data.get('frozen_after'),
data.get('change_amount'), data.get('source', 'manual'),
data.get('note', ''),
))
conn.commit()
return True, "现金变更已记录"
except Exception as e:
return False, str(e)
def query_cash_log(conn, limit: int = 20) -> list[dict]:
rows = conn.execute(
"SELECT * FROM cash_log ORDER BY id DESC LIMIT ?", (limit,)
).fetchall()
return [dict(r) for r in rows]