feat: 首页财务概览重构 — 5卡片合并为表格 + 费用列 + 环比列

- 5张独立财务卡片合并为一张表格(行=时间维度,列=6项指标)
- 新增费用列(数据源expense_records,单/多租户路径均支持)
- 每列增加环比列(季度累计行=季度环比,本月新增行=月度环比)
- 环比:正值绿+xx%,负值红-xx%
- 后端新增expense_annual/q2/month/prev_q/prev_month指标
This commit is contained in:
mac
2026-07-06 18:20:34 +08:00
parent 7ab0c71b54
commit 340f8bd88c
2 changed files with 81 additions and 20 deletions

View File

@@ -247,6 +247,7 @@ def bootstrap():
t_ops = attach_common(conn, "operations", rows(conn, "SELECT * FROM operation_projects WHERE tenant=? ORDER BY id ASC", [t]))
t_sales = attach_common(conn, "sales", rows(conn, "SELECT * FROM sales_leads WHERE tenant=? ORDER BY id DESC", [t]))
t_products = attach_common(conn, "products", rows(conn, "SELECT * FROM product_versions WHERE tenant=? ORDER BY id DESC", [t]))
t_expense = rows(conn, "SELECT * FROM expense_records WHERE tenant=?", [t])
t_proposals = attach_common(conn, "proposals", rows(conn, "SELECT * FROM business_proposals WHERE tenant=? ORDER BY id DESC", [t]))
t_signed_pfs = [x for x in t_pfs if x["status"] == "已签约"]
def t_parse_budget(pf):
@@ -305,10 +306,26 @@ def bootstrap():
"cost_prev_q": t_sum_budget("cost", _prev_q_range),
"cost_prev_month": t_sum_budget("cost", [_prev_month]) if _prev_month else 0,
})
# 费用汇总(从 expense_records 表计算)
def t_expense_sum(m_range):
total = 0
for r in t_expense:
m = (r.get("expense_month") or "").strip()
if not m or "-" not in m: continue
try:
if int(m.split("-")[1]) in m_range:
total += float(r.get("amount") or 0)
except: pass
return total
all_metrics[-1]["expense_annual"] = t_expense_sum(range(1, 13))
all_metrics[-1]["expense_q2"] = t_expense_sum(_q_range)
all_metrics[-1]["expense_month"] = t_expense_sum([_now_month])
all_metrics[-1]["expense_prev_q"] = t_expense_sum(_prev_q_range)
all_metrics[-1]["expense_prev_month"] = t_expense_sum([_prev_month]) if _prev_month else 0
all_monthly.append(monthly_finance(conn, t))
all_recent.extend(rows(conn, "SELECT * FROM follow_up_records WHERE tenant=? ORDER BY id DESC LIMIT 4", [t]))
agg = {}
for key in ["total_projects","total_proposals","total_products","upcoming_products","signed_amount","signed_annual","signed_q2","signed_month","signed_prev_q","signed_prev_month","revenue_annual","revenue_q2","monthly_revenue","revenue_prev_q","revenue_prev_month","gross_annual","gross_q2","monthly_net_profit","gross_prev_q","gross_prev_month","payment_annual","payment_q2","payment_month","payment_prev_q","payment_prev_month","cost_annual","cost_q2","cost_month","cost_prev_q","cost_prev_month"]:
for key in ["total_projects","total_proposals","total_products","upcoming_products","signed_amount","signed_annual","signed_q2","signed_month","signed_prev_q","signed_prev_month","revenue_annual","revenue_q2","monthly_revenue","revenue_prev_q","revenue_prev_month","gross_annual","gross_q2","monthly_net_profit","gross_prev_q","gross_prev_month","payment_annual","payment_q2","payment_month","payment_prev_q","payment_prev_month","cost_annual","cost_q2","cost_month","cost_prev_q","cost_prev_month","expense_annual","expense_q2","expense_month","expense_prev_q","expense_prev_month"]:
agg[key] = sum(m.get(key, 0) for m in all_metrics)
merged_monthly = []
for i in range(12):
@@ -380,6 +397,21 @@ def bootstrap():
cost_prev_q = sum_budget("cost", _prev_q_range)
payment_prev_month = sum_budget("payment", [_prev_month]) if _prev_month else 0
cost_prev_month = sum_budget("cost", [_prev_month]) if _prev_month else 0
def expense_sum(month_range):
total = 0
for r in expense:
m = (r.get("expense_month") or "").strip()
if not m or "-" not in m: continue
try:
if int(m.split("-")[1]) in month_range:
total += float(r.get("amount") or 0)
except: pass
return total
expense_annual = expense_sum(range(1, 13))
expense_q2 = expense_sum(_q_range)
expense_month_val = expense_sum([_now_month])
expense_prev_q = expense_sum(_prev_q_range)
expense_prev_month = expense_sum([_prev_month]) if _prev_month else 0
def pf_status_sum(status):
return sum(x["sign_amount"] or 0 for x in pfs if x["status"] == status)
signed_amount = pf_status_sum("已签约")
@@ -431,6 +463,11 @@ def bootstrap():
"cost_month": cost_month,
"cost_prev_q": cost_prev_q,
"cost_prev_month": cost_prev_month,
"expense_annual": expense_annual,
"expense_q2": expense_q2,
"expense_month": expense_month_val,
"expense_prev_q": expense_prev_q,
"expense_prev_month": expense_prev_month,
"signed_not_executed": signed_not_executed,
},
"recent": q("SELECT * FROM follow_up_records WHERE tenant=? ORDER BY id DESC LIMIT 8", tenant),