diff --git a/backend/migrations/__init__.py b/backend/migrations/__init__.py index a62d639..b37f4f9 100644 --- a/backend/migrations/__init__.py +++ b/backend/migrations/__init__.py @@ -17,7 +17,7 @@ def run_migrations(): """ from migrations.tables import migrate_create_tables from migrations.columns import migrate_add_columns - from migrations.data_fixes import migrate_fix_task_status, migrate_rename_tenant, migrate_drop_product_fields + from migrations.data_fixes import migrate_fix_task_status, migrate_rename_tenant, migrate_drop_product_fields, migrate_fix_service_fee_standard from migrations.seed import migrate_seed_users, migrate_seed_demo_data migrate_create_tables() @@ -25,5 +25,6 @@ def run_migrations(): migrate_fix_task_status() migrate_rename_tenant() migrate_drop_product_fields() + migrate_fix_service_fee_standard() migrate_seed_users() migrate_seed_demo_data() diff --git a/backend/migrations/columns.py b/backend/migrations/columns.py index 571892d..9895f14 100644 --- a/backend/migrations/columns.py +++ b/backend/migrations/columns.py @@ -75,6 +75,24 @@ def migrate_add_columns(): _add_column_if_missing(conn, "project_finances", "total_paid", "ALTER TABLE project_finances ADD COLUMN total_paid DOUBLE NOT NULL DEFAULT 0") + # project_finances 项目基本信息扩展字段 + _add_column_if_missing(conn, "project_finances", "project_code", + "ALTER TABLE project_finances ADD COLUMN project_code VARCHAR(50) NOT NULL DEFAULT ''") + _add_column_if_missing(conn, "project_finances", "start_date", + "ALTER TABLE project_finances ADD COLUMN start_date VARCHAR(30) NOT NULL DEFAULT ''") + _add_column_if_missing(conn, "project_finances", "end_date", + "ALTER TABLE project_finances ADD COLUMN end_date VARCHAR(30) NOT NULL DEFAULT ''") + _add_column_if_missing(conn, "project_finances", "task_type", + "ALTER TABLE project_finances ADD COLUMN task_type VARCHAR(100) NOT NULL DEFAULT ''") + _add_column_if_missing(conn, "project_finances", "task_count", + "ALTER TABLE project_finances ADD COLUMN task_count DOUBLE NOT NULL DEFAULT 0") + _add_column_if_missing(conn, "project_finances", "service_fee_standard", + "ALTER TABLE project_finances ADD COLUMN service_fee_standard DOUBLE NOT NULL DEFAULT 0") + _add_column_if_missing(conn, "project_finances", "project_manager", + "ALTER TABLE project_finances ADD COLUMN project_manager VARCHAR(100) NOT NULL DEFAULT ''") + _add_column_if_missing(conn, "project_finances", "task_data", + "ALTER TABLE project_finances ADD COLUMN task_data TEXT") + conn.commit() print("[migrate] 加列迁移完成") finally: diff --git a/backend/migrations/data_fixes.py b/backend/migrations/data_fixes.py index 3df69c7..8cfd7bf 100644 --- a/backend/migrations/data_fixes.py +++ b/backend/migrations/data_fixes.py @@ -71,3 +71,24 @@ def migrate_drop_product_fields(): print(f"[migrate] 删除 {col} 失败: {e}") finally: conn.close() + + +def migrate_fix_service_fee_standard(): + """修正 project_finances.service_fee_standard 旧数据为默认值 5(5%)""" + from db import db + + conn = db() + try: + cur = conn.cursor() + cur.execute( + "UPDATE project_finances SET service_fee_standard = 5 " + "WHERE service_fee_standard = 0 OR service_fee_standard IS NULL " + "OR service_fee_standard NOT IN (5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25)" + ) + affected = cur.rowcount + cur.close() + if affected: + conn.commit() + print(f"[migrate] project_finances: {affected} 条记录 service_fee_standard 修正为 5") + finally: + conn.close() diff --git a/backend/routes.py b/backend/routes.py index c7cb6be..a201488 100644 --- a/backend/routes.py +++ b/backend/routes.py @@ -23,7 +23,7 @@ TABLES = { "products": ("product_versions", ["product_name", "version", "version_goal", "priority", "start_date", "plan_date", "dev_done_date", "test_date", "launch_date", "status", "notes", "tenant"]), "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"]), + "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"]), } # ---------- 鉴权装饰器 ---------- diff --git a/static/modules/finance.js b/static/modules/finance.js index 95d4094..1fe0963 100644 --- a/static/modules/finance.js +++ b/static/modules/finance.js @@ -6,7 +6,7 @@ function renderFinance() { const pfs = state.data.projectFinances || []; const ops = state.data.operations || []; const fmTypesByTenant = { - "科普·无界": ["科普音频","科普视频","科普文章","全品类科普","调研问卷"], + "科普·无界": ["科普音频","科普视频","科普文章","科普专访","患教会","全品类科普","调研问卷"], "科研·无界": ["真实世界研究","调研问卷","病例征集","患者招募"], "医患·无界": ["医患运营","患者管理","患教会","创新支付","电商","其他"], }; @@ -110,26 +110,30 @@ function renderFinance() { ${[["本月确收",moneyInt(thisMonthRev),"trending-up"],["本月毛利",moneyInt(thisMonthGross),"percent"],["本月回款",moneyInt(monthPayment),"wallet"],["本月应付",moneyInt(monthCost),"receipt"],["本月现金流",moneyInt(monthCashflow),"repeat"]].map(([l,v,icon]) => `
${l}${v}
`).join("")}
-