重构:flask_app.py 拆分为 db/helpers/routes/seed_data + Blueprint
- flask_app.py 1166行→33行纯入口
- 新建 db.py(配置+连接+SQL工具)
- 新建 helpers.py(attach_common/monthly_finance/add_file_index)
- 新建 routes.py(全路由 Blueprint + 装饰器 + TABLES)
- 新建 migrations/seed_data.py(seed_db 搬迁)
- migrations/{tables,columns,data_fixes,seed}.py 改 import 为 from db
- 删除死代码 init_db(228行)+ latest_followup(10行)
- 反向依赖消除:migrations 不再 import flask_app
- 前端零改动,URL 不变
This commit is contained in:
105
backend/helpers.py
Normal file
105
backend/helpers.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# helpers.py — 业务查询辅助函数
|
||||
# 依赖:db.py;被 routes.py 和 migrations/seed_data.py 调用
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from db import _exec, rows, one
|
||||
|
||||
|
||||
def add_file_index(conn, module, owner_id, owner_version, category, path, external=True):
|
||||
path = Path(path)
|
||||
if not path.exists():
|
||||
return
|
||||
_exec(conn,
|
||||
"""INSERT INTO file_assets
|
||||
(module,owner_id,owner_version,file_category,file_name,file_type,file_size,file_path,is_external)
|
||||
VALUES (?,?,?,?,?,?,?,?,?)""",
|
||||
(module, owner_id, owner_version, category, path.name, path.suffix.lower().lstrip("."), path.stat().st_size, str(path), 1 if external else 0),
|
||||
)
|
||||
|
||||
|
||||
def attach_common(conn, resource, items):
|
||||
"""批量加载 followups 和 files,避免 N+1 查询"""
|
||||
if not items:
|
||||
return items
|
||||
target_map = {"sales": "sales", "proposals": "proposal", "operations": "operation", "products": "product"}
|
||||
target_type = target_map.get(resource)
|
||||
ids = [item["id"] for item in items]
|
||||
|
||||
# 批量查 followups(一次性 IN 查询)
|
||||
if target_type:
|
||||
placeholders = ",".join(["?"] * len(ids))
|
||||
all_followups = rows(
|
||||
conn,
|
||||
f"SELECT * FROM follow_up_records WHERE target_type=? AND target_id IN ({placeholders}) ORDER BY followed_at DESC, id DESC",
|
||||
[target_type] + ids,
|
||||
)
|
||||
followups_by_id = {}
|
||||
for fu in all_followups:
|
||||
followups_by_id.setdefault(fu["target_id"], []).append(fu)
|
||||
for item in items:
|
||||
item["followups"] = followups_by_id.get(item["id"], [])
|
||||
item["latest_follow_up_record"] = item["followups"][0]["content"] if item["followups"] else ""
|
||||
|
||||
# 批量查 files(proposals + operations)
|
||||
file_modules = {"proposals": "proposal", "operations": "operation"}
|
||||
if resource in file_modules:
|
||||
module = file_modules[resource]
|
||||
placeholders = ",".join(["?"] * len(ids))
|
||||
all_files = rows(
|
||||
conn,
|
||||
f"SELECT * FROM file_assets WHERE module=? AND owner_id IN ({placeholders}) ORDER BY id DESC",
|
||||
[module] + ids,
|
||||
)
|
||||
files_by_id = {}
|
||||
for f in all_files:
|
||||
files_by_id.setdefault(f["owner_id"], []).append(f)
|
||||
for item in items:
|
||||
item["files"] = files_by_id.get(item["id"], [])
|
||||
|
||||
return 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='已签约'",
|
||||
[tenant])
|
||||
|
||||
parsed_budgets = []
|
||||
for pf in pfs:
|
||||
try:
|
||||
budget = json.loads(pf.get("budget_data") or "[]")
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
budget = []
|
||||
budget_map = {}
|
||||
for b in budget:
|
||||
key = (b.get("month") or "").replace("-", "_")
|
||||
budget_map[key] = {
|
||||
"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),
|
||||
}
|
||||
parsed_budgets.append((pf, budget_map))
|
||||
|
||||
data = []
|
||||
for month in months:
|
||||
key = month.replace("-", "_")
|
||||
revenue = gross = payment = cost = sign = 0
|
||||
for pf, budget_map in parsed_budgets:
|
||||
if pf["status"] == "已签约" and (pf.get("sign_month") or "") == month:
|
||||
sign += float(pf["sign_amount"] or 0)
|
||||
b = budget_map.get(key)
|
||||
if b:
|
||||
revenue += b["rev"]
|
||||
gross += b["gross"]
|
||||
payment += b["payment"]
|
||||
cost += b["cost"]
|
||||
data.append({
|
||||
"month": month, "revenue": revenue,
|
||||
"labor": 0, "expense": 0, "purchase": 0,
|
||||
"gross": gross,
|
||||
"sign": sign, "payment": payment, "cost": cost,
|
||||
})
|
||||
return data
|
||||
Reference in New Issue
Block a user