TRACEIQ / 财务 Agent / 工程实施与验收方案

Excel 公式导出实施计划

从只读证据快照,升级到可解释、可重算、可对账的财务工作簿。

状态:待实施 · 本文不是功能已完成或生产验收通过的证明

核查日期:2026-09-23 | 交付范围:计划文档,不修改现有导出逻辑

01 / 核查结论:目前不含公式

当前 XLSX 导出不满足本次需求。

现有实现将每个单元格转换为字符串,并明确设置为文本类型。导出的收入、成本和毛利贡献是结果快照,没有可重算公式,也没有完整的行列字典和操作说明。

核查对象已存在的行为与目标的差距
finance/views.py · export()一张“证据明细”;前四行含版本 SHA、筛选上下文、ROI 口径、导出时间;所有值写为文本。没有公式计算层、汇总报表或说明页。
tests/test_finance.py · test_excel_export_precision_and_formula_safety明确断言所有单元格都不是公式,验证高精度金额及注入保护。只能证明证据快照行为正确,不能证明公式导出正确。
frontend/src/dialogs.tsx · EvidenceDialog选择 XLSX 下载证据明细。没有公式版选择、兼容性说明、精度提示或异步状态。
规模与参考附件现有单次导出上限 100,000 行;附件共有 332,830 行。不能通过现有接口一次导出原附件全部明细。

已运行的两项针对性测试:test_excel_export_precision_and_formula_safety、test_xlsx_double_header_and_lookup,结果 2 passed(1.59 秒)。后者验证导入双表头与毛利率匹配,不是 Excel 公式重算测试。

保留金额文本并非无意义限制:系统使用高精度 Decimal,而 Excel 普通数值只有约 15 位有效数字。新方案必须保留证据精度,不能直接把所有字符串改成浮点数。

02 / 设计选择与推荐

决策选项与代价推荐
导出模式A. 替换现有证据导出,破坏旧语义。
B. 保留证据快照,新增公式工作簿。
B。界面清楚区分“证据快照”和“公式分析工作簿”;CSV 始终是快照,不承诺公式。
精度A. 全部按 Excel 浮点数,丢失高精度证据。
B. 精确文本证据 + 数值计算层 + Decimal 对账。
C. 宏或自定义高精度插件,兼容、部署及安全成本高。
B。明确公式值遵守批准后的精度政策,不声称原生公式保持 24 位小数精确运算。
公式兼容性A. Microsoft 365,支持动态数组去重。
B. 旧版 Excel / WPS / LibreOffice,需另做兼容实现及验证。
先以 Microsoft 365 桌面 Windows / Mac 为明确验收目标;网页版另测。其他引擎通过验证后再声明支持,不能以应用跨平台替代工作簿兼容性。
人数计算A. UNIQUE/FILTER 真正按范围去重。
B. 服务端预制去重辅助表,修改客户或分组后可能失效。
C. 每行 COUNTIFS 扫全表,规模大时开销很高。
公式版选 A,限定报表分组数量并压测;B 仅作明确只读的兼容快照,不能冒充完全可重算。避免 C。
生成与重算A. 现有 openpyxl 写公式,打开 Excel 时重算。
B. 导出后由经验证的受控引擎重算并保存缓存。
C. 添加写缓存库,但缓存仍是服务器结果。
第一阶段 A + 真实 Excel 验收;首次打开前预览可能空白,必须告知。若业务要求下载即带可信缓存,则 B 是上线前置条件;不把 C 当作重算证明。
编辑能力A. 任意插行、改维度和期间并自动重建全部报表。
B. 固定导出范围,允许指定输入修改,结构性变化重新导出。
首版 B,边界容易验证;完整可变结构作为后续独立需求,不暗示已经支持。
大文件A. 同步放宽现有上限。
B. 数据库任务 + 独立 worker + 私有文件下载。
全量附件采用 B;复用项目已有任务处理模式,不预先引入新的消息队列。

03 / 工作簿结构与行列说明

输出放在前面,输入和证据放在后面。仅创建实际需要的页,不按每个指标拆页。所有名称均为规划,尚未实现。

工作表行与列的含义内容与用途
分析汇总每行一个指标或已选维度分组;列为本期、基期、差额、变化率、单位、可用状态。汇总金额、去重人数、比率由明细或计算结果引用产生;非加法指标不合计子组值。页首注明范围、期间、版本及模拟状态。
使用说明按主题分行:范围、粒度、字段、公式、操作、限制。字典列包括名称、业务含义、数据类型、单位、来源字段、可否修改、空值含义、公式与示例;另附版本、时区和支持的 Excel 版本。
参数与口径每行一个参数或产品毛利率;列为当前值、含义、来源、是否可改。收入映射、ROI 分支、自营产品集合、毛利率、精度政策;首版期间及筛选锁定。允许的模拟参数必须明确标识。
计算明细一行对应一个导入后的 Fact,保留来源定位键;不是一位客户或一次就诊。期间、维度、去标识客户 token、基础数值、原价、毛利来源、适用毛利率、毛利公式、缺失标志等;Excel Table 管理引用范围。
原始证据与计算明细一一对应;金额和标识保留精确文本。授权范围内的来源行、字段映射及原值;不可把完整患者原始信息无差别复制出去。工作表保护只防误操作,不是加密或权限控制。
对账检查每行一个指标及范围;列为服务器精确文本、批准精度的参考数值、公式结果、差异、阈值和检查状态。包含行数、缺失数、总分一致性、公式覆盖与精度警告;此页仅观察结果,不反向驱动业务公式。

说明页必须回答的问题

04 / 公式契约:每个衍生结果可追溯

基础事实可以是输入常量;新增衍生金额、计数、比率和差异必须来自真正的公式依赖。禁止用 =12345 或引用隐藏的静态答案来伪装计算。建立“指标 → 输入 → 公式 → 单位 → 缺失策略 → 测试”的显式清单。

指标计算定义边界与验收重点
收入 / 成本 / 原价在指定范围汇总对应基础字段。有数据但全为 0 与无数据不同;成本或原价部分缺失时依赖指标不可用,不能只合计非空项。
毛利贡献原始毛利有值时使用该输入;否则收入 × 已匹配产品毛利率;汇总逐行结果。必须恢复并记录 direct / lookup / missing 来源。Fact.gross 已是结果,不能直接把它当作原始毛利来伪造推导。必要时从保留的 raw 与映射提取,先做一致性测试。
ROIprofit_over_cost:(收入 − 成本) / 成本;gross_less_cost_over_cost:(毛利贡献 − 成本) / 成本。遵从数据版本映射;成本 ≤ 0 或任何必要字段缺失时不可用。
消费人数 / 客单价范围内客户 token 去重计数;收入 / 消费人数。跨月、跨产品、跨科室重复客户只计一次;有任一缺失客户时与现有后端口径一致地不可用。
毛利率 / 产品扣率毛利贡献 / 收入;收入 / 原价金额。先汇总再相除,不能平均行级比率;分母必须大于 0;不把扣率解释为“1 − 比值”。
自营收入 / 升单率配置自营产品范围内收入;该范围客户去重数 / 全部客户去重数。产品集合未配置时不可用;不能以自营收入占比替代升单率。
原价客单价原价金额 / 去重人数。原价或客户缺失时不可用。
差额 / 变化率本期 − 基期;差额 / ABS(基期)。基期 0 不计算变化率;缺期不比较;比率指标同时注明差额单位。
贡献率子组金额差额 / 父组金额差额。仅收入、成本、毛利、自营收入等可加指标;父级差额 0 不计算,不为人数或比率伪造加法贡献。

公式示例与生成规则

下列为设计样例。Data 表名、英文列名和命名范围须由模板定义,不能让用户字符串直接拼入公式;状态判断在拥有该指标的计算层生成。公式使用英文函数名和 OOXML 语法,实际写入动态数组需要验证序列化及兼容前缀。

收入(已确认该期间有记录):
=SUMIFS(Data[Revenue],Data[Period],CurrentPeriod)

成本完整性检查后计算 ROI:
=IF(CostStatus<>"OK",NA(),IF(Cost<=0,NA(),(Revenue-Cost)/Cost))

变化率(先确认本期与基期可比较):
=IF(Comparable=0,NA(),IF(BaselineValue=0,NA(),
 (CurrentValue-BaselineValue)/ABS(BaselineValue)))

365 去重人数(先确认范围有记录,且该范围客户字段完整):
=IF(CustomerStatus<>"OK",NA(),
 ROWS(UNIQUE(FILTER(Data[CustomerToken],Data[Period]=CurrentPeriod))))

毛利计算分支:
=IF([@GrossSource]="direct",[@GrossInput],
 IF([@RateStatus]="OK",[@Revenue]*[@MarginRate],NA()))

多月、多维度条件需生成对应掩码;上述单月例子不能直接替代完整上下文。全量、大量分组不允许每个明细行扫描全表。公式构建须限制报告维度及单元格数量。

缺失表达推荐:计算层用预期的 NA() 阻止错误结果传播;输出页用配套状态显示“不可用:缺成本”等原因。只对已知状态做展示转换,不用 IFERROR(...,0) 吞掉真实公式错误。

05 / 精度与财务对账

推荐:原始精确文本不可变,计算数值有明确精度契约。

“显示两位小数”不是“计算只用两位小数”。原附件有 11,990 行收入超过四位小数,不能在导出时静默按行截断。

  1. 证据层:保留 Decimal 原始字符串及来源映射;不经 JavaScript Number 中转。完整金额不可因导出而发生舍入。
  2. 计算层:先检测有效数字、数量级和累计误差风险,再转换 Excel 数值。把转换策略、舍入位数、舍入模式和发生时点写入文件。
  3. 推荐默认:分析公式不逐行强制 ROUND;展示金额两位,最终财务比较按批准的规则舍入。若业务要求“每行先舍入再汇总”,另设明确版本口径,不能混用。
  4. 两套参照:Decimal 对原始业务口径的精确结果用于证据核验;按相同批准数值政策得到的参考结果用于 Excel 计算对账。区别“政策导致的差异”与“实现错误”。
  5. 误差门槛:逐项规定金额绝对误差、比率误差及人数严格相等。建议金额以最终批准币种最小单位一致为目标;具体阈值必须经真实样本和财务确认,不能先放宽到让测试通过。
  6. 边界处理:超过可接受数值范围、舍入临界点或差异超阈值时阻止宣称“精确一致”,给出可定位的警告或拒绝公式版,证据版仍保留。

不推荐启用 Excel“以显示精度为准”,因为它会改变存储值。原生数值公式不能承诺任意 24 位小数精确运算;若确有此硬要求,应保留服务端 Decimal 为权威计算引擎,并另行评估高精度插件,不在首版隐式引入宏。

06 / 修改后究竟会重算什么

操作首版承诺限制
修改允许编辑的收入、成本、原价、直接毛利行级毛利、汇总、比率、差额及对账随公式重算。原始证据不变;明确标记为本地模拟,不回写服务器。
修改已有产品的毛利率仅 lookup 来源行重算;direct 来源行不受影响。不自动新增产品,不静默替换原始毛利。
筛选或隐藏明细行默认仅改变可见行,不改变汇总范围。明确 SUMIFS 不随 AutoFilter 改变;若未来要“仅可见行汇总”,作为独立模式实现及测试。
改变期间、维度、客户、产品集合,追加或删除行首版不承诺;从系统重新选择范围并导出。Table 能扩展不等于分组报表、去重及状态范围全部正确扩展;锁定结构以防误解。
修改公式默认保护防误操作;允许授权副本解除保护后自行分析。解除保护后的结果不属于系统验证范围;工作表保护不是安全边界。

源事实 ID 或稳定行键只用于追溯;本地模拟状态可通过可编辑输入与导出初值比较生成。任何数据版本 SHA 都只标识服务器来源,不能认证已被本地修改的文件。

07 / 安全、权限与 33 万行性能

可信公式与不可信内容严格分离

任务化导出

保留旧同步证据入口的行为;新增公式版任务状态:queued → running → succeeded / failed / expired。请求校验后冻结数据版本、映射、筛选、权限范围、参数和公式版本。worker 用分块迭代处理,临时文件原子完成后才发布;支持超时、失败重试、去重请求、崩溃恢复和过期清理。

真实附件 332,830 行未超过 Excel 单表 1,048,576 行的限制,但当前接口的 100,000 行限制仍然存在。完整公式版必须另做容量评估,超过支持范围应显式拒绝或提示缩小范围,不能悄悄截断。

性能基准至少覆盖 1,000 / 100,000 / 332,830 行,测导出耗时、峰值内存、文件大小、首次打开、改值重算、并发排队。记录设备、Excel 版本和数据分组基数;本轮不虚构 SLA。高基数分组达到预算时提示缩小报表范围,不降级为静态结果却仍标“公式版”。

08 / 文件级实施步骤

阶段工作与目标文件完成条件 / 依赖
P0 · 口径冻结
估计 1–2 人日
复核 finance/analysis.py、finance/importing.py 与原附件;定义精度政策、公式清单、编辑边界及兼容矩阵;确认毛利来源恢复。财务确认收入 N / 实收 I、原价、退款、自营产品、成本与 ROI;否则不可冻结黄金结果。
P1 · 最小公式工作簿
估计 2–4 人日
新增 finance/exporting.py 集中生成模板、状态和公式;复用现有分析口径,不引入通用公式 DSL。先实现小样本汇总、明细、参数、说明和对账。每个衍生单元格可追溯;输入/公式/文本写入类型分离;小样本真实 Excel 重算通过。
P2 · 精度与隐私
估计 1–2 人日
同模块实现精确文本、数值转换预检、毛利来源、客户 token、来源定位和注入防护;增加针对性单元测试。Decimal 对账、去重、缺失、恶意文本及越权用例通过;不破坏证据版。
P3 · 任务与 API
估计 2–3 人日
在 finance/models.py 增加必要的导出任务与迁移;在 finance/views.py 及现有 URL 配置增加提交/查询/下载入口;新增导出 worker 命令,复用导入 worker 的部署模式。完整附件能异步生成;崩溃恢复、重试、权限撤销、留存清理可验证。schema_version、mode、context、compatibility 等字段由服务端白名单校验。
P4 · 网页交互
估计 1–2 人日
frontend/src/dialogs.tsx、types.ts、api.ts 按需调整:模式选择、兼容性与精度说明、任务状态、错误反馈、下载和重试。桌面/手机可用;不显示无依据百分比;错误不丢失筛选上下文;CSV 与旧 XLSX 行为清晰保留。
P5 · 引擎与全量验收
估计 3–5 人日
新增 tests/test_exporting.py、扩展 tests/e2e/workspace.spec.ts;编写受控重算与差异报告脚本;更新 docs/acceptance.md。下节所有适用门禁有可复现记录;33 万行性能验证及财务签字完成。

合计粗估 10–18 人日,用于排期,不是承诺。受控 Excel 测试环境、财务确认和超预算性能优化可能增加日历时间。P1 小样本原型通过后再投入大文件任务流程;各阶段保持可单独审查和回滚。

兼容 API:旧 format=xlsx 默认仍为证据快照;新公式模式显式申请任务并返回任务 ID。服务端返回实际导出模式与版本,前端不凭文件后缀推断。

09 / 严格测试与上线门禁

写入公式不等于公式算对。

openpyxl 不执行计算;设置自动重算或 fullCalcOnLoad 也不是测试结果。必须在目标 Excel 引擎执行、保存,再同时读取公式和结果缓存验证。

测试层必须覆盖的场景通过标准
结构与公式覆盖每页、命名范围、Table、单元格类型、公式依赖、说明及数据验证;空数据导出。衍生区域全覆盖真实公式,基础输入无意外公式;无循环引用、损坏修复提示或外部链接。
财务黄金样例两种 ROI、direct/lookup 毛利、退款、负数、0、缺成本、部分缺字段、缺期、基期0、新增/消失分组。与独立 Decimal 预期一致到批准精度;人数完全相等;缺失不能变0。
客户去重同人跨科室/产品/月,重复明细、自营与非自营交集、空客户字段。总体不相加子组人数;升单率分子去重正确;缺客户状态与系统一致。
真实引擎重算Excel Windows / Mac;打开重算保存;分别读取 formula 与 data_only;修改收入、成本、原价及毛利率后再次计算。受影响链路变化符合独立预期,非依赖指标不误变。扫描 #REF!、#DIV/0!、#VALUE!、#NAME?、#SPILL!;仅允许明确缺失状态对应的 #N/A。
精度极限15位边界、24位小数、极大金额、正负抵消、舍入临界值、33万行累计差异。精确文本不变;超出政策明确报警或拒绝;不通过放宽误差掩盖错误。
注入与越权恶意标签/原始公式、工作表名特殊字符、跨组织/科室、任务 ID 猜测、下载前撤权。无执行不可信公式、外链或敏感原值泄露;未授权下载拒绝并审计。
任务可靠性重复提交、worker中断、磁盘不足、超时、并发、到期清理。无半成品下载、孤儿文件和静默截断;失败可解释,恢复无重复发布。
前端与兼容回归两模式选择、状态、错误重试、下载、移动端;现有 CSV/XLSX。浏览器端到端通过;旧证据版仍保持精度与公式注入防护。新公式版测试只允许白名单公式,不删除旧安全断言。
真实附件全量332,830行;2025-08/2026-08及原映射;全量与分组对账。行数不缺失,金额满足政策,人数为33,147 / 38,361;缺成本 ROI 不可用,未配置自营范围不擅自补值。

发布清单(全部待实施验证)

上线先小范围授权用户试用公式模式,旧证据导出保留作为回退。只有 Excel 导出门禁通过,不意味着整个财务系统所有商业上线门禁自动满足。

10 / 需确认的业务决策

可直接采用的工程默认

  • 双模式并存,公式版 XLSX 不含宏和外链。
  • 精确证据 + 数值计算 + 对账,不牺牲原始精度。
  • Microsoft 365 为首版公式验收目标。
  • 固定范围、指定输入可改,结构变化重新导出。
  • 大文件异步、授权下载、客户去标识。

上线前必须由财务确认

  • 收入继续使用 N 列,还是另需 I 列实收口径?
  • 舍入在每行还是最终汇总发生?使用哪种舍入规则与容差?
  • 毛利率允许本地模拟吗?直接毛利是否允许修改?
  • 自营产品集合、退款计人、成本归属及 ROI 口径是什么?
  • 是否必须支持旧版 Excel/WPS,以及首次打开前就有结果缓存?

建议实施顺序:先确认口径与 Excel 版本 → 小样本真正公式与重算验证 → 33 万行任务化及性能测试 → 前端完整交互与财务签字。不要先把导出值改成数值、加几条 SUM,就标记需求完成。