"""migrations/data_split.py — 预算数据拆分迁移:budget_data → expense_data 旧结构:budget_data = [{month, rev, gross, payment, cost, paid}] 新结构:expense_data = [{month, expense_type, cost, paid, exp_note}] 部署时自动:检测未拆分的旧数据,将 cost/paid 从 budget_data 迁移到 expense_data。 幂等:只处理 expense_data 为空的记录。 """ def migrate_data_split(): """一次性数据拆分迁移""" from db import db, _exec import json conn = db() try: # 查询未迁移的记录 cur = conn.cursor(dictionary=True) cur.execute( "SELECT id, budget_data, expense_data FROM project_finances " "WHERE (expense_data IS NULL OR expense_data = '' OR expense_data = '[]') " "AND budget_data IS NOT NULL AND budget_data != '' AND budget_data != '[]'" ) rows = cur.fetchall() cur.close() migrated = 0 for row in rows: try: budget = json.loads(row.get("budget_data") or "[]") except (json.JSONDecodeError, TypeError): continue expense_rows = [] for b in budget: expense_rows.append({ "month": b.get("month", ""), "expense_type": "", "cost": float(b.get("cost") or 0), "paid": float(b.get("paid") or 0), "exp_note": "", }) if expense_rows: _exec( conn, "UPDATE project_finances SET expense_data = ? WHERE id = ?", (json.dumps(expense_rows, ensure_ascii=False), row["id"]), ) migrated += 1 conn.commit() print(f"[migrate] 数据拆分迁移完成:{migrated} 条记录已从 budget_data 提取 cost/paid 到 expense_data") finally: conn.close()