feat: 新增采购模块 + 财务表格重建

采购模块:
- 新增 purchase_records 表 + CRUD 路由 + bootstrap 数据加载
- 前端采购管理页面: 表格 + 弹窗新增/编辑 + 侧边栏入口

财务模块:
- 表格新增签约金额、执行率、回款率、付款率、毛利、毛利率列
- 状态/日期筛选统一为无边框下拉框,移至页面顶部工具栏
- 删除 metric 卡片,新增 11 张汇总卡片(签约金额~现金流)
- 表格合计行移至表头下方,后改为汇总卡片
- 所有单元格统一水平/垂直居中
- 修复季度视图 gross 变量缺失、合计行遗漏
This commit is contained in:
mac
2026-07-06 13:04:56 +08:00
parent ff7eb19d5d
commit 8430c93b97
6 changed files with 148 additions and 25 deletions

View File

@@ -146,6 +146,20 @@ def migrate_create_tables():
budget_data TEXT,
created_at VARCHAR(30) NOT NULL DEFAULT '',
updated_at VARCHAR(30) NOT NULL DEFAULT ''
)""",
"""CREATE TABLE IF NOT EXISTS purchase_records (
id INT AUTO_INCREMENT PRIMARY KEY,
tenant VARCHAR(100) NOT NULL DEFAULT '科普·无界',
project_name VARCHAR(200) NOT NULL DEFAULT '',
purchase_item VARCHAR(300) NOT NULL DEFAULT '',
supplier VARCHAR(200) NOT NULL DEFAULT '',
amount DOUBLE NOT NULL DEFAULT 0,
purchase_date VARCHAR(30) NOT NULL DEFAULT '',
status VARCHAR(50) NOT NULL DEFAULT '待审批',
category VARCHAR(100) NOT NULL DEFAULT '',
notes VARCHAR(1000) NOT NULL DEFAULT '',
created_at VARCHAR(30) NOT NULL DEFAULT '',
updated_at VARCHAR(30) NOT NULL DEFAULT ''
)""",
]

View File

@@ -24,6 +24,7 @@ TABLES = {
"finance": ("finance_records", ["month", "project_name", "record_type", "category", "amount", "occurred_date", "notes", "tenant"]),
"tasks": ("project_tasks", ["project_id", "phase", "milestone", "task", "owner", "due_date", "blockers", "notes", "status", "sort_order", "priority", "tenant"]),
"projectFinances": ("project_finances", ["project_id", "tenant", "business_type", "customer_name", "sign_amount", "sign_month", "status", "sales_person", "owner", "total_rev", "total_gross", "total_payment", "total_cost", "total_paid", "budget_data", "start_date", "end_date", "task_type", "task_count", "service_fee_standard", "project_manager", "task_data", "project_code", "contact_name", "contact_phone", "other_info"]),
"purchase": ("purchase_records", ["project_name", "purchase_item", "supplier", "amount", "purchase_date", "status", "category", "notes", "tenant"]),
}
# ---------- 鉴权装饰器 ----------
@@ -321,7 +322,7 @@ def bootstrap():
"recent": sorted(all_recent, key=lambda x: x.get("id", 0), reverse=True)[:8],
"risks": [],
}
return jsonify({"summary": summary, "sales": [], "proposals": [], "operations": [], "products": [], "finance": [], "projectFinances": [], "financeMonthly": merged_monthly, "tasks": [], "tenant": tenant, "tenants": allowed})
return jsonify({"summary": summary, "sales": [], "proposals": [], "operations": [], "products": [], "finance": [], "projectFinances": [], "financeMonthly": merged_monthly, "tasks": [], "purchase": [], "tenant": tenant, "tenants": allowed})
def q(sql, *args):
return rows(conn, sql, args)
@@ -332,6 +333,7 @@ def bootstrap():
finance = q("SELECT * FROM finance_records WHERE tenant=? ORDER BY month DESC, id DESC", tenant)
tasks = q("SELECT * FROM project_tasks WHERE tenant=? ORDER BY phase, sort_order, id", tenant)
pfs = q("SELECT * FROM project_finances WHERE tenant=? ORDER BY id DESC", tenant)
purchase = q("SELECT * FROM purchase_records WHERE tenant=? ORDER BY id DESC", tenant)
signed_pfs = [x for x in pfs if x["status"] == "已签约"]
def parse_budget(pf):
@@ -434,7 +436,7 @@ def bootstrap():
"recent": q("SELECT * FROM follow_up_records WHERE tenant=? ORDER BY id DESC LIMIT 8", tenant),
"risks": [{"title": "执行提醒", "content": x["next_action"]} for x in operations if x["next_action"]][:5],
}
return jsonify({"summary": summary, "sales": sales, "proposals": proposals, "operations": operations, "products": products, "finance": finance, "projectFinances": pfs, "financeMonthly": monthly_finance(conn, tenant), "tasks": tasks, "tenant": tenant, "tenants": allowed})
return jsonify({"summary": summary, "sales": sales, "proposals": proposals, "operations": operations, "products": products, "finance": finance, "projectFinances": pfs, "financeMonthly": monthly_finance(conn, tenant), "tasks": tasks, "purchase": purchase, "tenant": tenant, "tenants": allowed})
finally:
conn.close()