From 6853b755b8db3588703af5ca6a3944c82c5a8781 Mon Sep 17 00:00:00 2001 From: mac Date: Tue, 7 Jul 2026 19:00:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=83=A8=E9=97=A8=E7=BB=8F=E8=90=A5?= =?UTF-8?q?=E8=A1=A8=E6=96=B0=E5=A2=9E=E9=A1=B9=E7=9B=AE=E7=8E=B0=E9=87=91?= =?UTF-8?q?=E6=B5=81/=E9=83=A8=E9=97=A8=E8=B4=B9=E7=94=A8=E5=B7=B2?= =?UTF-8?q?=E4=BB=98/=E9=83=A8=E9=97=A8=E7=8E=B0=E9=87=91=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 部门毛利 → 项目毛利 - 新增行: 项目现金流、部门费用(已付)、部门现金流 - 后端 expense_paid_sum 计算平台费用已付(排除暂不计入) - 总工作台同步兼容 - 版本号 v1.0.0.8 --- backend/routes.py | 54 +++++++++++++++++++++++++++++++++++++++++- static/modules/home.js | 14 +++++++---- templates/index.html | 2 +- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/backend/routes.py b/backend/routes.py index 15d9a19..6e33122 100644 --- a/backend/routes.py +++ b/backend/routes.py @@ -359,6 +359,27 @@ def bootstrap(): all_metrics[-1]["cashflow_month"] = all_metrics[-1]["payment_month"] - all_metrics[-1]["paid_month"] all_metrics[-1]["cashflow_prev_q"] = all_metrics[-1]["payment_prev_q"] - all_metrics[-1]["paid_prev_q"] all_metrics[-1]["cashflow_prev_month"] = all_metrics[-1]["payment_prev_month"] - all_metrics[-1]["paid_prev_month"] + def t_expense_paid_sum(m_range): + total = 0 + for r in t_expense: + if (r.get("status") or "") == "暂不计入": continue + 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("incurred_amount") or 0) + except: pass + return total + all_metrics[-1]["expense_paid_annual"] = t_expense_paid_sum(range(1, 13)) + all_metrics[-1]["expense_paid_q2"] = t_expense_paid_sum(_q_range) + all_metrics[-1]["expense_paid_month"] = t_expense_paid_sum([_now_month]) + all_metrics[-1]["expense_paid_prev_q"] = t_expense_paid_sum(_prev_q_range) + all_metrics[-1]["expense_paid_prev_month"] = t_expense_paid_sum([_prev_month]) if _prev_month else 0 + all_metrics[-1]["dept_cf_annual"] = all_metrics[-1]["cashflow_annual"] - all_metrics[-1]["expense_paid_annual"] + all_metrics[-1]["dept_cf_q2"] = all_metrics[-1]["cashflow_q2"] - all_metrics[-1]["expense_paid_q2"] + all_metrics[-1]["dept_cf_month"] = all_metrics[-1]["cashflow_month"] - all_metrics[-1]["expense_paid_month"] + all_metrics[-1]["dept_cf_prev_q"] = all_metrics[-1]["cashflow_prev_q"] - all_metrics[-1]["expense_paid_prev_q"] + all_metrics[-1]["dept_cf_prev_month"] = all_metrics[-1]["cashflow_prev_month"] - all_metrics[-1]["expense_paid_prev_month"] all_metrics[-1]["profit_annual"] = all_metrics[-1]["gross_annual"] - all_metrics[-1]["proj_expense_annual"] all_metrics[-1]["profit_q2"] = all_metrics[-1]["gross_q2"] - all_metrics[-1]["proj_expense_q2"] all_metrics[-1]["profit_month"] = all_metrics[-1]["monthly_net_profit"] - all_metrics[-1]["proj_expense_month"] @@ -367,7 +388,7 @@ def bootstrap(): 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","expense_annual","expense_q2","expense_month","expense_prev_q","expense_prev_month","paid_annual","paid_q2","paid_month","paid_prev_q","paid_prev_month","cashflow_annual","cashflow_q2","cashflow_month","cashflow_prev_q","cashflow_prev_month","profit_annual","profit_q2","profit_month","profit_prev_q","profit_prev_month","proj_expense_annual","proj_expense_q2","proj_expense_month","proj_expense_prev_q","proj_expense_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","paid_annual","paid_q2","paid_month","paid_prev_q","paid_prev_month","cashflow_annual","cashflow_q2","cashflow_month","cashflow_prev_q","cashflow_prev_month","expense_paid_annual","expense_paid_q2","expense_paid_month","expense_paid_prev_q","expense_paid_prev_month","dept_cf_annual","dept_cf_q2","dept_cf_month","dept_cf_prev_q","dept_cf_prev_month","profit_annual","profit_q2","profit_month","profit_prev_q","profit_prev_month","proj_expense_annual","proj_expense_q2","proj_expense_month","proj_expense_prev_q","proj_expense_prev_month"]: agg[key] = sum(m.get(key, 0) for m in all_metrics) merged_monthly = [] for i in range(12): @@ -473,6 +494,22 @@ def bootstrap(): 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 expense_paid_sum(month_range): + total = 0 + for r in expense: + if (r.get("status") or "") == "暂不计入": continue + 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("incurred_amount") or 0) + except: pass + return total + expense_paid_annual = expense_paid_sum(range(1, 13)) + expense_paid_q2 = expense_paid_sum(_q_range) + expense_paid_month = expense_paid_sum([_now_month]) + expense_paid_prev_q = expense_paid_sum(_prev_q_range) + expense_paid_prev_month = expense_paid_sum([_prev_month]) if _prev_month else 0 paid_annual = sum_expense("paid", range(1, 13)) paid_q2 = sum_expense("paid", _q_range) paid_month = sum_expense("paid", [_now_month]) @@ -488,6 +525,11 @@ def bootstrap(): cashflow_month = payment_month - paid_month cashflow_prev_q = payment_prev_q - paid_prev_q cashflow_prev_month = payment_prev_month - paid_prev_month + dept_cf_annual = cashflow_annual - expense_paid_annual + dept_cf_q2 = cashflow_q2 - expense_paid_q2 + dept_cf_month = cashflow_month - expense_paid_month + dept_cf_prev_q = cashflow_prev_q - expense_paid_prev_q + dept_cf_prev_month = cashflow_prev_month - expense_paid_prev_month profit_annual = gross_annual - proj_expense_annual profit_q2 = gross_q2 - proj_expense_q2 profit_month = gross_month - proj_expense_month @@ -559,6 +601,16 @@ def bootstrap(): "cashflow_month": cashflow_month, "cashflow_prev_q": cashflow_prev_q, "cashflow_prev_month": cashflow_prev_month, + "expense_paid_annual": expense_paid_annual, + "expense_paid_q2": expense_paid_q2, + "expense_paid_month": expense_paid_month, + "expense_paid_prev_q": expense_paid_prev_q, + "expense_paid_prev_month": expense_paid_prev_month, + "dept_cf_annual": dept_cf_annual, + "dept_cf_q2": dept_cf_q2, + "dept_cf_month": dept_cf_month, + "dept_cf_prev_q": dept_cf_prev_q, + "dept_cf_prev_month": dept_cf_prev_month, "profit_annual": profit_annual, "profit_q2": profit_q2, "profit_month": profit_month, diff --git a/static/modules/home.js b/static/modules/home.js index ce693bd..e9f89ad 100644 --- a/static/modules/home.js +++ b/static/modules/home.js @@ -126,7 +126,7 @@ function renderHome() { ${card(`

部门经营情况

${(() => { var d = [ - ['部门毛利', [m.profit_annual||0, m.profit_q2||0, m.profit_month||0, m.profit_prev_q||0, m.profit_prev_month||0], + ['项目毛利', [m.profit_annual||0, m.profit_q2||0, m.profit_month||0, m.profit_prev_q||0, m.profit_prev_month||0], [m.profit_q2||0,m.profit_prev_q||0], [m.profit_month||0,m.profit_prev_month||0]], ['部门费用', [m.expense_annual||0, m.expense_q2||0, (m.expense_month||0), m.expense_prev_q||0, m.expense_prev_month||0], [m.expense_q2||0,m.expense_prev_q||0], [(m.expense_month||0),m.expense_prev_month||0]], @@ -137,11 +137,17 @@ function renderHome() { (m.profit_q2||0)-(m.expense_q2||0), (m.profit_prev_q||0)-(m.expense_prev_q||0) ], [ (m.profit_month||0)-(m.expense_month||0), (m.profit_prev_month||0)-(m.expense_prev_month||0) - ]] + ]], + ['项目现金流', [m.cashflow_annual||0, m.cashflow_q2||0, m.cashflow_month||0, m.cashflow_prev_q||0, m.cashflow_prev_month||0], + [m.cashflow_q2||0,m.cashflow_prev_q||0], [m.cashflow_month||0,m.cashflow_prev_month||0]], + ['部门费用(已付)', [m.expense_paid_annual||0, m.expense_paid_q2||0, m.expense_paid_month||0, m.expense_paid_prev_q||0, m.expense_paid_prev_month||0], + [m.expense_paid_q2||0,m.expense_paid_prev_q||0], [m.expense_paid_month||0,m.expense_paid_prev_month||0]], + ['部门现金流', [m.dept_cf_annual||0, m.dept_cf_q2||0, m.dept_cf_month||0, m.dept_cf_prev_q||0, m.dept_cf_prev_month||0], + [m.dept_cf_q2||0,m.dept_cf_prev_q||0], [m.dept_cf_month||0,m.dept_cf_prev_month||0]] ]; var h = ''; - var netCls = function(di, raw) { return di === 2 ? (raw >= 0 ? 'text-green-600' : 'text-red-600') : 'text-slate-800'; }; - for (var di = 0; di < 3; di++) { + var netCls = function(di, raw) { if (di === 2 || di === 5) return raw >= 0 ? 'text-green-600' : 'text-red-600'; if (di === 3) return raw >= 0 ? 'text-green-600' : 'text-red-600'; return 'text-slate-800'; }; + for (var di = 0; di < 6; di++) { var r = d[di]; h += '' + '' + diff --git a/templates/index.html b/templates/index.html index be9efed..48851f6 100644 --- a/templates/index.html +++ b/templates/index.html @@ -76,7 +76,7 @@
-

OPC Manager v1.0.0.7

+

OPC Manager v1.0.0.8

科普 OPC 工作台

指标年度累计上季度累计上月累计本季度累计季环比本月累计月环比
' + r[0] + '' + moneyInt(r[1][0]) + '