feat: 项目流水拆分为确收与回款+费用明细两Tab + 数据迁移

后端:
- 新增 expense_data TEXT 列(columns.py迁移)
- 新增 data_split 迁移:旧 budget_data cost/paid → expense_data(幂等)
- sum_budget cost/paid → sum_expense cost/paid(routes.py/helpers.py)
- TABLES 配置加入 expense_data

前端:
- 项目详情弹窗Tab:基本信息→确收与回款→费用明细→执行信息→任务管理→活动
- 确收与回款Tab:月份/确收/毛利/回款/备注
- 费用明细Tab:月份/费用类型/应付/已付/备注
- 项目表格三视图(月/季/总)cost/paid来源切换为expense_data
- 保存逻辑分两路: budget_data(rev/gross/payment)+expense_data(cost/paid)
This commit is contained in:
mac
2026-07-06 21:34:48 +08:00
parent dbc98e4693
commit f44f7eab9e
6 changed files with 275 additions and 89 deletions

View File

@@ -63,10 +63,11 @@ def attach_common(conn, resource, items):
def monthly_finance(conn, tenant="科普·无界"):
months = [f"2026-{m:02d}" for m in range(1, 13)]
pfs = rows(conn,
"SELECT sign_amount, sign_month, status, budget_data FROM project_finances WHERE tenant=? AND status='已签约'",
"SELECT sign_amount, sign_month, status, budget_data, expense_data FROM project_finances WHERE tenant=? AND status='已签约'",
[tenant])
parsed_budgets = []
expense_maps = {}
for pf in pfs:
try:
budget = json.loads(pf.get("budget_data") or "[]")
@@ -79,11 +80,23 @@ def monthly_finance(conn, tenant="科普·无界"):
"rev": float(b.get("rev") or 0),
"gross": float(b.get("gross") or 0),
"payment": float(b.get("payment") or 0),
"cost": float(b.get("cost") or 0),
"paid": float(b.get("paid") or 0),
}
parsed_budgets.append((pf, budget_map))
# Parse expense_data for cost/paid
try:
ed = json.loads(pf.get("expense_data") or "[]")
except (json.JSONDecodeError, TypeError):
ed = []
em = {}
for e in ed:
key = (e.get("month") or "").replace("-", "_")
em[key] = {
"cost": float(e.get("cost") or 0),
"paid": float(e.get("paid") or 0),
}
expense_maps[pf.get("id", id(pf))] = em
data = []
for month in months:
key = month.replace("-", "_")
@@ -96,8 +109,11 @@ def monthly_finance(conn, tenant="科普·无界"):
revenue += b["rev"]
gross += b["gross"]
payment += b["payment"]
cost += b["cost"]
paid += b["paid"]
em = expense_maps.get(pf.get("id", id(pf)), {})
e = em.get(key)
if e:
cost += e["cost"]
paid += e["paid"]
data.append({
"month": month,
"revenue": round(revenue, 2),