8.3 KiB
8.3 KiB
预算版本管理 操作手册
模块 slug: budget-version(对应队列 cma-module-queue.json) 最近一次修复后状态定稿:2026-09-07(project-20260907-budget-version-ui-fix 完成并验证后) 使用本手册前请先读「④ 已知边界/坑」——本模块历史上反复出现字段/状态机错位,改前必查。
① 模块定位
- 模块名:预算版本管理(Budget Version Management)
- 解决什么问题:年度预算允许保留多个版本(如零基 v1.0/v2.0、年度 2026H2),支持"编制 → 提交审批 → 批准/驳回 → 重新提交"的版本状态机,以及两个版本间的差异对比。防止把"草稿中版本"误当"已批准版本"执行。
- 所属流程环节:预算 → 版本管理(预算编制/分解/执行的上游容器;预算计划行挂在具体 version 下,active 版本为当前生效版本)
- 主要角色:finance(编制/提交审批)、ceo(批准/驳回)、it(维护),entity1=陕西酣客、entity2=陕西博海
② 操作步骤
页面路径:登录后侧边栏「预算管理」(/budget,zone B 可编辑)→ 顶部 tab「版本管理」。
- 查看版本列表(默认按当年 year 加载)
- 版本列表加载:前端调
GET /api/cma/budget/versions?year=YYYY(返回裸数组,前端需Array.isArray(r) ? r : r.data || []解包) - 列含义:
版本(标签,当前生效版本绿色高亮并带「(当前)」后缀) |状态(审批状态标签:草稿/待审批/已批准/已驳回) |条目数(plan_count=预算行数) |总额(total_budget) |最后更新(last_updated, YYYY-MM-DD HH:MM) |操作(按状态出按钮)
- 版本列表加载:前端调
- 状态机流转(DB
budget_plans.status原值 vs UI 展示approval_status)- UI 语义:
draft(可提交审批) →submitted(待审批) →approved(已批准只读) /rejected(已驳回可重新提交) - 后端映射:DB 默认态
active→ UI 展示为draft(服务端语义收敛,approval_status = "draft" if status=="active" else status);approved/submitted/rejected 原样透传。DB status 保留 active/approved/submitted/rejected 四种,勿改 DB 值语义(active=当前生效版本,版本下拉「(当前)」标记依赖status==='active')
- UI 语义:
- 提交审批:状态为「草稿」的行 → 点「提交审批」→ 确认弹窗 → 后端
POST /api/cma/budget/versions/submit(body{"version": "v2026H2"}),状态 active → submitted - 审批:状态为「待审批」的行 → 点「批准」(
POST /versions/approvebody action=approved,submitted → approved) 或「驳回」(action=rejected,submitted → rejected) - 重新提交:状态为「已驳回」的行 → 点「重新提交」(复用 submit 端点,rejected → submitted)
- 已批准只读:approved 版本操作列无任何按钮,不可再提交/修改(只读语义,正确表现即无按钮)
- 版本差异对比:勾选列表左侧复选框(最多 2 个,超过自动取消最早勾选)→ 点「版本差异对比」→ 弹窗展示两版本逐期间/逐 KPI 差异(
POST /api/cma/budget/versions/diff,body 含 version_a/version_b/year) - 预算行编制在「预算编制」相关 tab 内按当前选中版本录入(顶部版本下拉 filterVersion 选择后 loadBudget)
③ 验证路径
- 自动脚本:
- 生产 API 双账套断言:
/root/cma-management/backend/scripts/verify_budget_versions_ui_fix.py(cd backend && venv/bin/python3 scripts/verify_budget_versions_ui_fix.py;用 admin/admin123 分别登录 entity1/entity2,断言新字段存在 + active→draft 映射 + plan_count==kpi_count + last_updated==updated_at) - 浏览器页面 DOM 实测:
/root/cma-management/backend/scripts/verify_budget_versions_ui_browser.py(需先起 Chrome CDP 9224,命令见 cma-fullstack-ops 技能 references/budget-version-ui-field-state-fix-20260907.md 的 Chrome 起法;登录博海 entity2 断言 v2026H2 行=草稿/25条/462/最后更新非空/「提交审批」按钮,切酣客 entity1 断言 5 个 active 行有提交按钮 + 2026H2 approved「已批准」无按钮)
- 生产 API 双账套断言:
- 期望输出:两个脚本末尾均输出
ALL_PASS且 exit 0 - 已测基线(最近一次验证日期+结果):2026-09-07 复跑双脚本 ALL_PASS。实测数据:博海 entity2
v2026H2 | status=active | approval_status=draft | plan_count=25 | total=462.0 | last_updated='2026-08-30 11:24';酣客 entity1 共 6 版本,5 个 active(v1.0/v2.0/incremental/flexible/zero_based-20260826)→ 草稿+「提交审批」按钮,2026H2 approved → 「已批准」无按钮
④ 已知边界 / 坑
- 历史 bug:
- 2026-09-04 版本列表永远为空:后端
list_budget_versions返回裸数组,前端 axios 拦截器剥层后r.data为 undefined → 空列表无报错。修复 commit 46096e8:前端Array.isArray兼容解包。同根因 bug 出现在 BudgetManagement.vue loadVersions,全仓扫描见技能 axios-unwrap-bare-array reference - 2026-09-07 用户反馈「版本管理仅有操作复选框」:两个独立 bug 叠加——①前端列取
approval_status/plan_count/last_updated而后端返回status/kpi_count/updated_at→ 状态列恒显示 else 分支「草稿」、条目数/最后更新恒空白;②DBbudget_plans.status默认态是active(不在前端按钮条件 draft/submitted/rejected 里)→ active 行整行无按钮。修复 commit b01a108:后端输出补approval_status(active→draft 映射)+plan_count+last_updated且保留 status/kpi_count/updated_at 原字段;前端按钮条件补|| row.approval_status === 'active'双端保险
- 2026-09-04 版本列表永远为空:后端
- 边界条件:
- active(=UI draft)可提交审批;approved 只读(无按钮、不应有编辑入口);submitted 只能批准/驳回不能重复提交;rejected 可重新提交
- 版本下拉「(当前)」标记用 DB 原字段
status==='active',与 UI approval_status 展示解耦——两字段都必须在接口里 - 版本「选中当前版本」逻辑:加载版本后默认选
status==='active'的版本,避免全版本堆叠重复期间(2026-08-27 根治)
- ⚠️ 易踩点:
- 后端返回字段改名必须保留原字段别名——前端/测试契约(下拉「当前」标记、verify 脚本断言)依赖 status/kpi_count/updated_at
- approval_status 由后端统一映射,勿在前端做 DB 状态翻译(会出现双端不一致)
/versions端点返回裸数组是既有契约,改后端请勿包一层 data(会复现 09-04 空列表 bug);改前端勿忘 Array.isArray 解包- 验证脚本(浏览器版)存在 tab 创建竞态(Target.createTarget 后偶发 about:blank → localStorage SecurityError),已加导航等待(commit 616f444);复跑若挂先确认 Chrome 起法与 host-resolver-rules
⑤ 修改记录
| 日期 | 修改人 | 改动 | commit | 影响 |
|---|---|---|---|---|
| 2026-09-07 | - | 手册创建(修复后状态定稿) | - | - |
| 2026-09-07 | 全栈Bot | UI字段/状态机对齐:后端补 approval_status(active→draft)/plan_count/last_updated + 前端按钮 active 兜底 | b01a108 |
修复「版本管理只有复选框」 |
| 2026-09-07 | 全栈Bot | 验证脚本入库(API+浏览器双录) | f8018aa |
可复跑资产 |
| 2026-09-07 | 全栈Bot | 浏览器验证脚本 tab 竞态加导航等待 | 616f444 |
修复复跑必挂 |
| 2026-09-04 | 全栈Bot | loadVersions 裸数组解包 bug 修复 | 46096e8 |
修复版本列表永远为空 |
| 2026-08-27 | 全栈Bot | 加载版本默认选中当前 active 版本 | - | 防全版本堆叠 |
⑥ 关联
- 依赖表:budget_plans(version/status/period/amount 等,预算行按 version 归属)、kpi_definitions(预算行关联 KPI)
- 依赖接口:GET /api/cma/budget/versions;POST /api/cma/budget/versions/submit;POST /api/cma/budget/versions/approve;POST /api/cma/budget/versions/diff(均带 Depends(get_entity_id) 账套隔离)
- 关联模块:预算编制/分解(auto-decompose,批量分解幂等)、预算执行(execution)、预编报表(proforma reports 取 active 版本预算);前端 BudgetManagement.vue
- 验证资产:backend/scripts/verify_budget_versions_ui_fix.py(API)、verify_budget_versions_ui_browser.py(浏览器 CDP)