chore: import existing codebase as baseline
Verify / verify (push) Failing after 1m20s

This commit is contained in:
Jayway Liu
2026-09-26 01:12:10 +08:00
commit 0ac0c4eb56
77 changed files with 14155 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
# 验收状态与上线门禁
日期:2026-09-24,Asia/Singapore。本文区分实现状态和验证状态,不把编译成功等同于生产商用验收。
## 公式工作簿与对话新增列
本轮新增校验:对话模型、导出 API 及最终工作簿生成器均只允许引用当前数据映射可计算的指标;模型误报完整或客户端绕过对话直接提交时,服务端仍会拒绝缺少来源字段的自定义列。
> **当前发布判断:** 本轮后端 61 passed、finance 覆盖率 87.66%;公式工作簿版本 3 已改为流式写入,100,000 行产品上限实测峰值 RSS 约 136.4 MB。新增列流程覆盖追问、补充、定义确认、数据映射可用性防护及公式工作簿下载。LibreOffice 重算测试覆盖特定黄金样例;Microsoft Excel、财务口径签字、真实 AI 合规、原附件 332,830 行范围方案及目标环境部署仍未验收。
| 需求 | 状态 | 实现 / 尚缺内容 |
| --- | --- | --- |
| 对话定义自定义列 | 已实现;mock 端到端通过 | 用户描述列名、含义、范围及计算;缺项时模型主动追问,补充后结合全对话重审;只接受既有指标/常数和白名单运算树。编辑补充时保留当前定义供核对,未发送的草稿会禁用确认;最多 6 轮,限 10 列、8 层表达式。真实外部模型联调未做。 |
| 自定义列公式导出 | 已实现;小样本验证通过 | 异步任务生成 XLSX;自定义列引用汇总指标公式,并包含使用说明、参数口径、计算明细、原始证据和对账页;另保留原有证据快照导出。 |
| Excel 公式引擎验收 | 尚未通过发布门禁 | 消费人数与升单率改用随机去标识 CustomerRoster 固定人数表 + COUNTIFS,不依赖 UNIQUE/FILTER;4 项 LibreOfficeDev 重算测试已通过。Microsoft Excel 仅打开过样本并在公式栏看到 COUNTIFS/SUMIFS;Excel 为只读无法保存重算副本,且所见分组与预期不匹配,故 Excel 实机重算结果仍未验收。身份、分组和期间是固定快照,编辑金额可重算,不支持通过改客户身份改变人数。 |
| 生产上线资格 | 未完成 | 公式导出最大 100,000 行/200 组,真实附件 332,830 行尚不能一次导出;真实 AI 服务联调、数据出境审批、目标 Excel 兼容、性能及安全审查均未完成。 |
## 最新验证(2026-09-24)
- 对话新增列及公式导出回归:后端全量 `61 passed`,finance 覆盖率 `87.66%`;新增用例覆盖流式工作簿、精确文本条件、未分类对账、Excel 长度限制、公式注入、保留列冲突、任务文件权限/路径、授权快照顺序和路径准备失败恢复。
- 当前源码自动化基线(2026-09-24):61 passed,finance 覆盖率 87.66%(85% 门槛);包含列定义追问、数据映射可用性防护、流式导出和 LibreOffice 公式重算回归。Ruff lint/format、TypeScript/Vite 构建、Django check、迁移检查通过。
- 本轮隔离 SQLite Playwright:3 passed、1 skipped;新增列追问与下载、桌面综合工作流、手机布局通过;原附件 UI 用例因未设置 `REFERENCE_DATASET_NAME` 跳过。隔离数据库和媒体目录位于 `/tmp/caiwu-roadmap-e2e*`;登录成功的正式用例使用临时口令环境变量。
- 完整临时生产配置下 `check --deploy` 无告警;pip-audit 和 npm audit 均为 0 已知漏洞。Docker 镜像构建未运行(Docker daemon 不可连接),Compose 校验未运行(真实 `.env` 不存在)。
- 真实附件 PostgreSQL 17 对账通过:332,830 行、5 个分组,收入/毛利/人数与历史独立对账一致,缺成本 332,830 行、ROI 不可用。完整公式工作簿生成基准 96.94 秒、51,532,457 字节、峰值 RSS 3,308,617,728 字节;单机单次生成不等于资源/SLA 通过。
- 本轮以安装的 LibreOfficeDev 执行 `tests/test_formula_recalculation.py`(3 项)与 `tests/test_formula_recalculation_gross.py`(1 项):共 4 项通过,覆盖自定义汇总/变化率、编辑明细金额后的联动、零成本 ROI、缺失基期,以及 direct/lookup 毛利来源。该结果不是 Microsoft Excel 实机验收。
- 流式容量基准:公式版本 3 的 20,000 行合成工作簿生成 5.26 秒、3,265,273 字节、峰值 RSS 77,922,304 字节;100,000 行生成 25.96 秒、16,217,767 字节、峰值 RSS 136,429,568 字节。100,000 行产物 ZIP/OOXML 完整性、7 个工作表、表格关系、版本及汇总公式读取通过;这是本机隔离 SQLite 单次基准,不是目标环境并发 SLA。
- Microsoft Excel 桌面检查记录:在只读 Excel 中打开 `/tmp/caiwu-excel-validation.xlsx`,公式栏可见 COUNTIFS/SUMIFS;无法保存重算副本,且所选样例分组为 `Test`、与预期不匹配。结果仅证明样本中存在公式,不证明 Excel 计算正确,发布门禁维持未通过。
- `compose.yaml` 已配置 `cleanup_formula_exports --loop` 常驻清理服务,清理逻辑有 3 项测试覆盖;目标环境仍需确认运行与告警。
## 剩余功能与发布阻断
| P0 | Microsoft Excel 公式引擎验收 | 已有 LibreOfficeDev 小样本公式缓存证据,仍需目标 Excel Windows/Mac 重算和兼容性验收。 |
| P0 | 真实附件范围与业务口径 | 100,000 行/200 组产品上限已用流式版本实测;原附件 332,830 行仍超范围,需选择可审计分卷或正式提高上限后再验。财务签字仍未完成。 |
| P0 | 真实 AI 合规与商用环境 | 真实模型联调、数据出境/隐私审批和目标环境安全验证尚缺。 |
| 优先级 | 未完成项 | 发布影响 / 下一步 |
| --- | --- | --- |
| P0 | Microsoft Excel 公式引擎验收 | 人数公式使用静态去重辅助表 + COUNTIFS;仍需目标 Excel Windows/Mac 打开、重算、保存,覆盖人数、升单率、空集、缺期及金额编辑后的计算。 |
| P0 | 真实附件全量公式导出 | 当前上限 100,000 明细行/200 分组,原附件 332,830 行;100,000 行流式资源压测已完成,仍需定义切分导出并保证跨文件口径,或批准扩大产品范围后做 332,830 行目标引擎验收。 |
| P0 | 财务业务口径签字 | 确认 N 列实际收入与 I 列实收、退款、成本归属、毛利、ROI、升单、自营产品集和舍入规则;真实附件成本缺失且 ROI 不可用。 |
| P0 | 外部 AI 合规与真实联调 | 完成真实模型超时/限额/故障演练、数据出境和隐私审批;未批准前保持 AI 关闭。 |
| P1 | 对话定义可扩展性 | 当前仅支持既有指标/常数与加减乘除;不支持任意 Excel 函数、跨明细新聚合、按零替代/跳过缺失、生成维度列或保存复用定义。新能力需逐项安全与黄金样例验证。 |
| P1 | 工作簿操作完整性 | 当前固定导出范围,不支持在 Excel 增加明细行后自动扩展所有报表;结构变化需重新导出。验证参数编辑、结构变化提示、模板版本和列字典。 |
| P1 | 定义体验差距 | 证据弹窗已支持本期/基期切换并通过 E2E;公式定义对话仍没有持久化草稿/定义库。确认复用范围后实现并补 E2E。 |
| P1 | 商业部署验收 | Docker 构建、HTTPS/证书、PostgreSQL/TLS、备份恢复、并发/SLA、审计监控、渗透测试、AG Grid Enterprise 商用许可需在目标环境验证/审批。 |
## 需求覆盖
| 需求 | 状态 | 实现 / 尚缺内容 |
| --- | --- | --- |
| 网页前端、手机适配 | 已实现,本地浏览器回归 | React + 响应式 CSS,无原生客户端 |
| XLSX/CSV、双行表头、解释型映射 | 已实现 | 标准别名建议 + 人工确认,不宣称通用 AI 自动识别全部表格 |
| 原始文件版本、重复上传、失败回滚 | 已实现并测试 | SHA-256 组织内唯一,源文件私有,成功版本不可修改 |
| 收入/毛利/成本/ROI/人数/客单价 | 已实现并测试 | 缺字段返回不可用;ROI 在导入时明确公式 |
| 自营收入/升单率/原价客单价 | 已实现并测试 | 新导入配置 self_operated_products;旧版本未配置时不可用,不偷偷改历史口径 |
| 同比/环比/自定义多月 | 已实现并测试 | 基期等长且不能重叠,缺失期间不比较 |
| 趋势/贡献/矩阵/异常列表 | 已实现 | ECharts 折线/横条图,非完整瀑布/Pareto/散点套件 |
| 动态下钻/面包屑/证据 | 已实现并测试 | 来源、区域、科室、学科、产品等映射维度;医生仅有字段才出现 |
| 设置保存/取消/预览、调查状态 | 已实现并测试 | 个人设置版本锁,调查按上下文持久化;没有团队工单分派 |
| CSV/Excel 导出 | 双模式已实现 | 既有 CSV/XLSX 为证据快照;公式 XLSX 为独立异步工作簿,含自定义公式列、说明页和固定人数去重辅助表。Microsoft Excel 引擎和全量附件门禁未通过,不可视为生产验收 |
| 账号/组织/科室权限/CSRF/审计 | 已实现并测试 | 应用层隔离;无数据库 RLS、SSO、MFA、自助密码找回 |
| Copilot | 本地规则助手可用;外部接口已实现 | 外部模型成功/拒答/非法意图以 mock 测试,尚未真实 API 联调 |
| AG Grid Enterprise | 部分接入 | 授权后注册模块;SSRM/Pivot/Tree Data/Master-Detail 未实现;现在使用服务端聚合 + 分页证据 |
| 全部过渡表口径重建 | 未完成 | 消费比率、实收/实际收入多口径、跨表 lookup 编辑、生效期毛利率、退款口径切换仍缺 |
| 异常规则 | 基础实现 | 不利变化率 + 影响金额 + 两期样本数;结构占比、历史分位数、告警投递尚未实现 |
| 原始附件 | 全量已导入并对账 | 不含医生/成本;只有两个单月,不允许虚构连续期间 |
| Docker/HTTPS/CI | 配置已交付,验证不完整 | Compose 使用示例环境文件替换后的配置校验通过;基础镜像 metadata 下载长时间无响应,已取消构建;无正式域名证书与远端 CI 运行记录 |
原始附件“过渡表2”同时使用“实收金额”“收入”“实际收入”字样,产品扣率分子存在歧义。当前产品扣率与客单价明确使用选定的实际收入字段,原附件采用 N 列;不能直接当作 I 列实收口径通过财务签字。旧导入版本也不会因为新代码增加自营产品范围而静默更改映射。
## 真实数据对账
来源 SHA-256:`98ef41e898c24f0929a9da6ec185b7331f69f0478b52056cbc7834e1ef5877ec`。
| 指标 | 2025-08 | 2026-08 |
| --- | ---: | ---: |
| 明细行数 | 157512 | 175318 |
| N 列实际收入 | 225550255.4187610638720 | 152419115.348455502666069 |
| 产品毛利贡献 | 24790335.405853982758000 | 17868580.85186759073400145 |
| 去重消费人数 | 33147 | 38361 |
总计 332830 行;收入同比 -32.4234%,毛利贡献同比 -27.9212%;ROI 不可用。独立逐行读取与数据库精确聚合一致,科室贡献变化合计等于总体变化。原数据 11990 行收入超过 4 位小数,未在落库时四舍五入到 4 位。
质量核查:负收入 12338 行、G/L 应收差异 14154 行、I/N 实收与实际收入差异 11991 行、成本缺失 332830 行、毛利率未匹配 0 行。本机单次完整查询约 3 秒,仅为一次开发机测量,不是并发性能 SLA。
## 测试记录
- 本轮源码测试:44 passed,finance 覆盖率 86.95%;常规 pytest 在本机 SQLite 测试配置运行,独立 PostgreSQL CI 未启动;另在本机 PostgreSQL 17 隔离库执行原附件对账和完整公式工作簿生成基准。
- 本轮浏览器回归:完整隔离 SQLite Playwright 3 passed、1 skipped;跳过未配置 `REFERENCE_DATASET_NAME` 的原附件 UI 专测。
- PostgreSQL 17:67 项后端测试通过(22.32 秒),finance 总覆盖率 89.17%,analysis 98%、assistant 90%、importing 86%、views 84%;CI 覆盖率门槛 85%。
- 检查内容:Decimal 金额、人数去重、加权比率、零分母、退款、缺期、新增/消失分组贡献、XLSX 表头与 lookup、导入原子性、重复上传、非法映射、跨组织/科室隔离、CSRF、会话、登录限流、设置冲突、调查记录、导出公式注入、模型意图白名单与敏感字段最小化、worker 恢复、CLI 初始化。
- TypeScript / Vite 生产构建通过;Django `check`、迁移检查及完整临时生产变量下的 `check --deploy` 均通过。目标部署环境仍未验收。
- Python pip-audit 与前端 npm audit(生产依赖)均报告 0 个已知漏洞;这不是渗透测试或未来无漏洞保证。
- 既有 Playwright 历史记录:3 项用例通过;当前分支 E2E 覆盖见上方 2026-09-24 最新验证,不能用历史结果替代本轮重跑。
- 回归发现并修复调查控件标签定位与图表网格最小宽度问题。原附件截图为 `reference-desktop.png` / `reference-mobile.png`;截图文件已生成,但工具未可靠展示图片供逐像素人工复核,视觉精修仍应由产品人员验收。
- 新增可信代理登录限流测试:未启用信任时忽略伪造客户端头,启用后仅接受合法 IP。生产 Caddy 覆盖 X-Real-IP,web 不得直接暴露公网。
- 产物位于本机 `test-results/`、`playwright-report/`,未提交真实财务数据和凭据。
## 必须完成的上线门禁
1. 财务负责人确认收入/实收/原价、退款、升单、自营、成本归属与 ROI 定义;补齐缺失的业务口径和字段。
2. 若要求原开发计划全部功能,补齐上述未完成项并逐项签字。当前版本不能标记为“所有前后端需求已完成”。
3. 在目标基础设施完成 Docker 镜像构建、HTTPS、数据库认证/TLS、上传限制、非 root 容器及重启恢复验收。
4. 用目标并发用户数、最大文件/维度基数做导入与查询压力测试,确定 SLA 和资源配额。当前聚合会返回所有分组,高基数维度需 SSRM 或服务端结果窗口。
5. 完成真实 OpenAI 接口联调、超时/限额演练和数据出境/隐私审批;没有审批时保持关闭。
6. 外部安全审查与渗透测试、最小权限数据库账号、密钥轮换、加密存储、访问日志脱敏、不可变审计与告警接入。
7. 执行数据库 + 源文件一致性备份及恢复演练,记录 RPO/RTO,确定留存和删除流程。
8. AG Grid Enterprise 若启用须有适用商业许可;完成所有依赖许可证盘点。
以上商用门禁不因本地自动化测试通过而自动满足;较早的 44、54 项测试及旧非流式 332,830 行峰值 RSS 约 3.31 GB 均为历史基线,不能替代当前版本的目标环境验收。
+45
View File
@@ -0,0 +1,45 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>财务 Agent · Excel 公式导出实施计划</title>
<style>
:root{color-scheme:light;--ink:#202725;--muted:#58645f;--line:#d8dfdc;--green:#17664f;--red:#ac3440;--bg:#f5f7f6}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);color:var(--ink);font:16px/1.8 system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;letter-spacing:0}header{background:#fff;border-bottom:3px solid var(--green);padding:40px 24px 28px}main,header>div,footer{max-width:1120px;margin:auto}h1{font-size:32px;line-height:1.35;margin:8px 0 16px}h2{font-size:24px;margin:0 0 18px}h3{font-size:18px;margin:24px 0 8px}p{margin:10px 0}small,.muted{color:var(--muted)}main{padding:0 24px}section{padding:32px 0;border-bottom:1px solid var(--line);scroll-margin-top:16px}nav{padding:22px 0;border-bottom:1px solid var(--line);display:flex;gap:12px 24px;flex-wrap:wrap}a{color:var(--green);text-underline-offset:4px}ul,ol{padding-left:24px}li{margin:8px 0}.notice{border-left:4px solid var(--red);padding:10px 18px;background:#fff}.recommend{border-left:4px solid var(--green);padding:10px 18px;background:#fff}.table-wrap{overflow:auto;max-width:100%;border:1px solid var(--line)}table{border-collapse:collapse;width:100%;min-width:720px;background:#fff;font-size:14px}th,td{text-align:left;vertical-align:top;padding:13px 15px;border-bottom:1px solid var(--line)}th{background:#eaf0ed}tr:last-child td{border-bottom:0}code{font:13px/1.7 ui-monospace,SFMono-Regular,Consolas,monospace;overflow-wrap:anywhere}pre{padding:16px;background:#eaf0ed;overflow:auto;max-width:100%;line-height:1.7}pre code{white-space:pre;overflow-wrap:normal}.tag{font-size:13px;font-weight:700;color:var(--red)}.grid{display:grid;grid-template-columns:1fr 1fr;gap:24px}.grid>div{min-width:0}footer{padding:28px 24px 48px;color:var(--muted);font-size:14px}strong{font-weight:650}@media(max-width:650px){header{padding:26px 18px}main{padding:0 18px}h1{font-size:26px}h2{font-size:21px}.grid{grid-template-columns:1fr;gap:0}section{padding:25px 0}}@media print{body{background:white;font-size:11pt}header{padding:0 0 16px}main{padding:0}nav{display:none}section{break-inside:auto;padding:18px 0}h2,h3{break-after:avoid}tr{break-inside:avoid}.table-wrap{overflow:visible}table{min-width:0;font-size:9pt}pre{white-space:pre-wrap}pre code{white-space:pre-wrap}footer{padding:16px 0}}
</style>
</head>
<body>
<aside style="max-width:1120px;margin:16px auto;padding:16px 24px;background:#fff4e5;border-left:4px solid #a95712"><strong>当前状态复核 · 2026-09-24:</strong>本页下方保留 2026-09-23 的历史实施方案,不能再据此判断当前功能状态。方案中的公式工作簿、说明页、异步导出和对话新增列已经实现;LibreOfficeDev 小样本重算已验证,Microsoft Excel Windows/Mac 尚未验收。当前限制为 100,000 行/200 组,332,830 行原附件公式工作簿、真实 AI 合规、财务签字和商业部署仍未通过。详情见 <a href="acceptance.md">验收状态与剩余门禁</a>。</aside>
<aside style="max-width:1120px;margin:16px auto;padding:16px 24px;background:#fff4e5;border-left:4px solid #a95712"><strong>状态更新 · 2026-09-24:</strong>本计划中的公式工作簿、说明页、异步导出及对话新增公式列已实现。新增列追问/导出专项、workspace 桌面和手机测试及后端测试通过。下方内容是实施前方案记录;目前仍未通过 Microsoft Excel 动态数组重算验收,LibreOffice 人数公式存在兼容错误;公式导出限制 100,000 行/200 组,无法一次覆盖 332,830 行附件;真实 AI 联调、财务口径签字及商业部署安全门禁未完成。因此公式版尚不具备生产发布资格。详见 <a href="acceptance.md">验收状态与剩余门禁</a>。</aside>
<header><div><small>TRACEIQ / 财务 Agent / 工程实施与验收方案</small><h1>Excel 公式导出实施计划</h1><p>从只读证据快照,升级到可解释、可重算、可对账的财务工作簿。</p><p class="tag">状态:待实施 · 本文不是功能已完成或生产验收通过的证明</p><small>核查日期:2026-09-23 | 交付范围:计划文档,不修改现有导出逻辑</small></div></header>
<main>
<nav aria-label="目录"><a href="#current">现状证据</a><a href="#decisions">设计选择</a><a href="#workbook">工作簿结构</a><a href="#formulas">公式与口径</a><a href="#precision">精度策略</a><a href="#editing">可重算边界</a><a href="#security">安全与性能</a><a href="#implementation">实施步骤</a><a href="#tests">测试与门禁</a><a href="#questions">待确认事项</a></nav>
<section id="current"><h2>01 / 核查结论:目前不含公式</h2><div class="notice"><strong>当前 XLSX 导出不满足本次需求。</strong><p>现有实现将每个单元格转换为字符串,并明确设置为文本类型。导出的收入、成本和毛利贡献是结果快照,没有可重算公式,也没有完整的行列字典和操作说明。</p></div><div class="table-wrap"><table><thead><tr><th>核查对象</th><th>已存在的行为</th><th>与目标的差距</th></tr></thead><tbody><tr><td><code>finance/views.py · export()</code></td><td>一张“证据明细”;前四行含版本 SHA、筛选上下文、ROI 口径、导出时间;所有值写为文本。</td><td>没有公式计算层、汇总报表或说明页。</td></tr><tr><td><code>tests/test_finance.py · test_excel_export_precision_and_formula_safety</code></td><td>明确断言所有单元格都不是公式,验证高精度金额及注入保护。</td><td>只能证明证据快照行为正确,不能证明公式导出正确。</td></tr><tr><td><code>frontend/src/dialogs.tsx · EvidenceDialog</code></td><td>选择 XLSX 下载证据明细。</td><td>没有公式版选择、兼容性说明、精度提示或异步状态。</td></tr><tr><td>规模与参考附件</td><td>现有单次导出上限 100,000 行;附件共有 332,830 行。</td><td>不能通过现有接口一次导出原附件全部明细。</td></tr></tbody></table></div><p>已运行的两项针对性测试:<code>test_excel_export_precision_and_formula_safety</code>、<code>test_xlsx_double_header_and_lookup</code>,结果 <strong>2 passed(1.59 秒)</strong>。后者验证导入双表头与毛利率匹配,不是 Excel 公式重算测试。</p><p>保留金额文本并非无意义限制:系统使用高精度 Decimal,而 Excel 普通数值只有约 15 位有效数字。新方案必须保留证据精度,不能直接把所有字符串改成浮点数。</p></section>
<section id="decisions"><h2>02 / 设计选择与推荐</h2><div class="table-wrap"><table><thead><tr><th>决策</th><th>选项与代价</th><th>推荐</th></tr></thead><tbody><tr><td>导出模式</td><td>A. 替换现有证据导出,破坏旧语义。<br>B. 保留证据快照,新增公式工作簿。</td><td><strong>B</strong>。界面清楚区分“证据快照”和“公式分析工作簿”;CSV 始终是快照,不承诺公式。</td></tr><tr><td>精度</td><td>A. 全部按 Excel 浮点数,丢失高精度证据。<br>B. 精确文本证据 + 数值计算层 + Decimal 对账。<br>C. 宏或自定义高精度插件,兼容、部署及安全成本高。</td><td><strong>B</strong>。明确公式值遵守批准后的精度政策,不声称原生公式保持 24 位小数精确运算。</td></tr><tr><td>公式兼容性</td><td>A. Microsoft 365,支持动态数组去重。<br>B. 旧版 Excel / WPS / LibreOffice,需另做兼容实现及验证。</td><td>先以 <strong>Microsoft 365 桌面 Windows / Mac</strong> 为明确验收目标;网页版另测。其他引擎通过验证后再声明支持,不能以应用跨平台替代工作簿兼容性。</td></tr><tr><td>人数计算</td><td>A. UNIQUE/FILTER 真正按范围去重。<br>B. 服务端预制去重辅助表,修改客户或分组后可能失效。<br>C. 每行 COUNTIFS 扫全表,规模大时开销很高。</td><td>公式版选 <strong>A</strong>,限定报表分组数量并压测;B 仅作明确只读的兼容快照,不能冒充完全可重算。避免 C。</td></tr><tr><td>生成与重算</td><td>A. 现有 openpyxl 写公式,打开 Excel 时重算。<br>B. 导出后由经验证的受控引擎重算并保存缓存。<br>C. 添加写缓存库,但缓存仍是服务器结果。</td><td>第一阶段 <strong>A + 真实 Excel 验收</strong>;首次打开前预览可能空白,必须告知。若业务要求下载即带可信缓存,则 B 是上线前置条件;不把 C 当作重算证明。</td></tr><tr><td>编辑能力</td><td>A. 任意插行、改维度和期间并自动重建全部报表。<br>B. 固定导出范围,允许指定输入修改,结构性变化重新导出。</td><td>首版 <strong>B</strong>,边界容易验证;完整可变结构作为后续独立需求,不暗示已经支持。</td></tr><tr><td>大文件</td><td>A. 同步放宽现有上限。<br>B. 数据库任务 + 独立 worker + 私有文件下载。</td><td>全量附件采用 <strong>B</strong>;复用项目已有任务处理模式,不预先引入新的消息队列。</td></tr></tbody></table></div></section>
<section id="workbook"><h2>03 / 工作簿结构与行列说明</h2><p>输出放在前面,输入和证据放在后面。仅创建实际需要的页,不按每个指标拆页。所有名称均为规划,尚未实现。</p><div class="table-wrap"><table><thead><tr><th>工作表</th><th>行与列的含义</th><th>内容与用途</th></tr></thead><tbody><tr><td>分析汇总</td><td>每行一个指标或已选维度分组;列为本期、基期、差额、变化率、单位、可用状态。</td><td>汇总金额、去重人数、比率由明细或计算结果引用产生;非加法指标不合计子组值。页首注明范围、期间、版本及模拟状态。</td></tr><tr><td>使用说明</td><td>按主题分行:范围、粒度、字段、公式、操作、限制。</td><td>字典列包括名称、业务含义、数据类型、单位、来源字段、可否修改、空值含义、公式与示例;另附版本、时区和支持的 Excel 版本。</td></tr><tr><td>参数与口径</td><td>每行一个参数或产品毛利率;列为当前值、含义、来源、是否可改。</td><td>收入映射、ROI 分支、自营产品集合、毛利率、精度政策;首版期间及筛选锁定。允许的模拟参数必须明确标识。</td></tr><tr><td>计算明细</td><td>一行对应一个导入后的 Fact,保留来源定位键;不是一位客户或一次就诊。</td><td>期间、维度、去标识客户 token、基础数值、原价、毛利来源、适用毛利率、毛利公式、缺失标志等;Excel Table 管理引用范围。</td></tr><tr><td>原始证据</td><td>与计算明细一一对应;金额和标识保留精确文本。</td><td>授权范围内的来源行、字段映射及原值;不可把完整患者原始信息无差别复制出去。工作表保护只防误操作,不是加密或权限控制。</td></tr><tr><td>对账检查</td><td>每行一个指标及范围;列为服务器精确文本、批准精度的参考数值、公式结果、差异、阈值和检查状态。</td><td>包含行数、缺失数、总分一致性、公式覆盖与精度警告;此页仅观察结果,不反向驱动业务公式。</td></tr></tbody></table></div><h3>说明页必须回答的问题</h3><ul><li>本文件覆盖哪个数据版本、期间、组织及筛选?这是授权范围快照,不代表整院所有数据。</li><li>金额单位是什么?百分比以小数储存;升单率变化“百分点”与相对变化率分列,不混用。</li><li>收入、实收、原价、毛利贡献分别指什么?毛利贡献不是净利润,ROI 成本的定义必须写明。</li><li>哪些单元格可改?颜色之外同时提供文字标签、批注和数据验证;公式格保护防止误覆盖。</li><li>如何启用自动计算、重新计算和查看公式?不需要启用宏,不连接外部数据,不回写业务系统。</li><li>空值、0、不可用、缺期和超精度分别是什么意思?遇到不支持函数时不要把错误当成 0。</li><li>修改后如何核对?本地修改是模拟结果,服务器原始快照及其 SHA 不因此变成修改后内容的认证。</li></ul></section>
<section id="formulas"><h2>04 / 公式契约:每个衍生结果可追溯</h2><p>基础事实可以是输入常量;新增衍生金额、计数、比率和差异必须来自真正的公式依赖。禁止用 <code>=12345</code> 或引用隐藏的静态答案来伪装计算。建立“指标 → 输入 → 公式 → 单位 → 缺失策略 → 测试”的显式清单。</p><div class="table-wrap"><table><thead><tr><th>指标</th><th>计算定义</th><th>边界与验收重点</th></tr></thead><tbody><tr><td>收入 / 成本 / 原价</td><td>在指定范围汇总对应基础字段。</td><td>有数据但全为 0 与无数据不同;成本或原价部分缺失时依赖指标不可用,不能只合计非空项。</td></tr><tr><td>毛利贡献</td><td>原始毛利有值时使用该输入;否则收入 × 已匹配产品毛利率;汇总逐行结果。</td><td>必须恢复并记录 direct / lookup / missing 来源。Fact.gross 已是结果,不能直接把它当作原始毛利来伪造推导。必要时从保留的 raw 与映射提取,先做一致性测试。</td></tr><tr><td>ROI</td><td>profit_over_cost:(收入 − 成本) / 成本;gross_less_cost_over_cost:(毛利贡献 − 成本) / 成本。</td><td>遵从数据版本映射;成本 ≤ 0 或任何必要字段缺失时不可用。</td></tr><tr><td>消费人数 / 客单价</td><td>范围内客户 token 去重计数;收入 / 消费人数。</td><td>跨月、跨产品、跨科室重复客户只计一次;有任一缺失客户时与现有后端口径一致地不可用。</td></tr><tr><td>毛利率 / 产品扣率</td><td>毛利贡献 / 收入;收入 / 原价金额。</td><td>先汇总再相除,不能平均行级比率;分母必须大于 0;不把扣率解释为“1 − 比值”。</td></tr><tr><td>自营收入 / 升单率</td><td>配置自营产品范围内收入;该范围客户去重数 / 全部客户去重数。</td><td>产品集合未配置时不可用;不能以自营收入占比替代升单率。</td></tr><tr><td>原价客单价</td><td>原价金额 / 去重人数。</td><td>原价或客户缺失时不可用。</td></tr><tr><td>差额 / 变化率</td><td>本期 − 基期;差额 / ABS(基期)。</td><td>基期 0 不计算变化率;缺期不比较;比率指标同时注明差额单位。</td></tr><tr><td>贡献率</td><td>子组金额差额 / 父组金额差额。</td><td>仅收入、成本、毛利、自营收入等可加指标;父级差额 0 不计算,不为人数或比率伪造加法贡献。</td></tr></tbody></table></div><h3>公式示例与生成规则</h3><p>下列为设计样例。<code>Data</code> 表名、英文列名和命名范围须由模板定义,不能让用户字符串直接拼入公式;状态判断在拥有该指标的计算层生成。公式使用英文函数名和 OOXML 语法,实际写入动态数组需要验证序列化及兼容前缀。</p><pre><code>收入(已确认该期间有记录):
=SUMIFS(Data[Revenue],Data[Period],CurrentPeriod)
成本完整性检查后计算 ROI:
=IF(CostStatus&lt;&gt;"OK",NA(),IF(Cost&lt;=0,NA(),(Revenue-Cost)/Cost))
变化率(先确认本期与基期可比较):
=IF(Comparable=0,NA(),IF(BaselineValue=0,NA(),
(CurrentValue-BaselineValue)/ABS(BaselineValue)))
365 去重人数(先确认范围有记录,且该范围客户字段完整):
=IF(CustomerStatus&lt;&gt;"OK",NA(),
ROWS(UNIQUE(FILTER(Data[CustomerToken],Data[Period]=CurrentPeriod))))
毛利计算分支:
=IF([@GrossSource]="direct",[@GrossInput],
IF([@RateStatus]="OK",[@Revenue]*[@MarginRate],NA()))</code></pre><p>多月、多维度条件需生成对应掩码;上述单月例子不能直接替代完整上下文。全量、大量分组不允许每个明细行扫描全表。公式构建须限制报告维度及单元格数量。</p><p><strong>缺失表达推荐:</strong>计算层用预期的 <code>NA()</code> 阻止错误结果传播;输出页用配套状态显示“不可用:缺成本”等原因。只对已知状态做展示转换,不用 <code>IFERROR(...,0)</code> 吞掉真实公式错误。</p></section>
<section id="precision"><h2>05 / 精度与财务对账</h2><div class="recommend"><strong>推荐:原始精确文本不可变,计算数值有明确精度契约。</strong><p>“显示两位小数”不是“计算只用两位小数”。原附件有 11,990 行收入超过四位小数,不能在导出时静默按行截断。</p></div><ol><li><strong>证据层:</strong>保留 Decimal 原始字符串及来源映射;不经 JavaScript Number 中转。完整金额不可因导出而发生舍入。</li><li><strong>计算层:</strong>先检测有效数字、数量级和累计误差风险,再转换 Excel 数值。把转换策略、舍入位数、舍入模式和发生时点写入文件。</li><li><strong>推荐默认:</strong>分析公式不逐行强制 ROUND;展示金额两位,最终财务比较按批准的规则舍入。若业务要求“每行先舍入再汇总”,另设明确版本口径,不能混用。</li><li><strong>两套参照:</strong>Decimal 对原始业务口径的精确结果用于证据核验;按相同批准数值政策得到的参考结果用于 Excel 计算对账。区别“政策导致的差异”与“实现错误”。</li><li><strong>误差门槛:</strong>逐项规定金额绝对误差、比率误差及人数严格相等。建议金额以最终批准币种最小单位一致为目标;具体阈值必须经真实样本和财务确认,不能先放宽到让测试通过。</li><li><strong>边界处理:</strong>超过可接受数值范围、舍入临界点或差异超阈值时阻止宣称“精确一致”,给出可定位的警告或拒绝公式版,证据版仍保留。</li></ol><p>不推荐启用 Excel“以显示精度为准”,因为它会改变存储值。原生数值公式不能承诺任意 24 位小数精确运算;若确有此硬要求,应保留服务端 Decimal 为权威计算引擎,并另行评估高精度插件,不在首版隐式引入宏。</p></section>
<section id="editing"><h2>06 / 修改后究竟会重算什么</h2><div class="table-wrap"><table><thead><tr><th>操作</th><th>首版承诺</th><th>限制</th></tr></thead><tbody><tr><td>修改允许编辑的收入、成本、原价、直接毛利</td><td>行级毛利、汇总、比率、差额及对账随公式重算。</td><td>原始证据不变;明确标记为本地模拟,不回写服务器。</td></tr><tr><td>修改已有产品的毛利率</td><td>仅 lookup 来源行重算;direct 来源行不受影响。</td><td>不自动新增产品,不静默替换原始毛利。</td></tr><tr><td>筛选或隐藏明细行</td><td>默认仅改变可见行,不改变汇总范围。</td><td>明确 SUMIFS 不随 AutoFilter 改变;若未来要“仅可见行汇总”,作为独立模式实现及测试。</td></tr><tr><td>改变期间、维度、客户、产品集合,追加或删除行</td><td>首版不承诺;从系统重新选择范围并导出。</td><td>Table 能扩展不等于分组报表、去重及状态范围全部正确扩展;锁定结构以防误解。</td></tr><tr><td>修改公式</td><td>默认保护防误操作;允许授权副本解除保护后自行分析。</td><td>解除保护后的结果不属于系统验证范围;工作表保护不是安全边界。</td></tr></tbody></table></div><p>源事实 ID 或稳定行键只用于追溯;本地模拟状态可通过可编辑输入与导出初值比较生成。任何数据版本 SHA 都只标识服务器来源,不能认证已被本地修改的文件。</p></section>
<section id="security"><h2>07 / 安全、权限与 33 万行性能</h2><h3>可信公式与不可信内容严格分离</h3><ul><li>公式只由受控模板生成;原始文本、列名、维度标签保持文本类型。保留并扩展当前 =、+、-、@、制表符及换行注入测试。</li><li>无 VBA、DDE、外部工作簿链接或未经允许的 HYPERLINK;扫描 OOXML 关系和公式,不只检查文件扩展名。</li><li>客户去重使用工作簿内稳定的去标识 token。推荐每次导出独立密钥 HMAC,在所有页统一使用,密钥不写入文件;仍按敏感数据管理,不能称为不可逆匿名化。</li><li>申请、执行、下载三个阶段复核组织和科室权限;执行快照只包含授权行,下载前权限被撤销必须拒绝。原始证据页也不能绕过字段权限。</li><li>下载文件私有存储、短期保留、自动清理;审计记录版本、范围、模式、公式版本、结果及文件哈希,不记录患者原值。</li></ul><h3>任务化导出</h3><p>保留旧同步证据入口的行为;新增公式版任务状态:queued → running → succeeded / failed / expired。请求校验后冻结数据版本、映射、筛选、权限范围、参数和公式版本。worker 用分块迭代处理,临时文件原子完成后才发布;支持超时、失败重试、去重请求、崩溃恢复和过期清理。</p><p>真实附件 332,830 行未超过 Excel 单表 1,048,576 行的限制,但当前接口的 100,000 行限制仍然存在。完整公式版必须另做容量评估,超过支持范围应显式拒绝或提示缩小范围,不能悄悄截断。</p><p>性能基准至少覆盖 1,000 / 100,000 / 332,830 行,测导出耗时、峰值内存、文件大小、首次打开、改值重算、并发排队。记录设备、Excel 版本和数据分组基数;本轮不虚构 SLA。高基数分组达到预算时提示缩小报表范围,不降级为静态结果却仍标“公式版”。</p></section>
<section id="implementation"><h2>08 / 文件级实施步骤</h2><div class="table-wrap"><table><thead><tr><th>阶段</th><th>工作与目标文件</th><th>完成条件 / 依赖</th></tr></thead><tbody><tr><td>P0 · 口径冻结<br>估计 1–2 人日</td><td>复核 <code>finance/analysis.py</code>、<code>finance/importing.py</code> 与原附件;定义精度政策、公式清单、编辑边界及兼容矩阵;确认毛利来源恢复。</td><td>财务确认收入 N / 实收 I、原价、退款、自营产品、成本与 ROI;否则不可冻结黄金结果。</td></tr><tr><td>P1 · 最小公式工作簿<br>估计 2–4 人日</td><td>新增 <code>finance/exporting.py</code> 集中生成模板、状态和公式;复用现有分析口径,不引入通用公式 DSL。先实现小样本汇总、明细、参数、说明和对账。</td><td>每个衍生单元格可追溯;输入/公式/文本写入类型分离;小样本真实 Excel 重算通过。</td></tr><tr><td>P2 · 精度与隐私<br>估计 1–2 人日</td><td>同模块实现精确文本、数值转换预检、毛利来源、客户 token、来源定位和注入防护;增加针对性单元测试。</td><td>Decimal 对账、去重、缺失、恶意文本及越权用例通过;不破坏证据版。</td></tr><tr><td>P3 · 任务与 API<br>估计 2–3 人日</td><td>在 <code>finance/models.py</code> 增加必要的导出任务与迁移;在 <code>finance/views.py</code> 及现有 URL 配置增加提交/查询/下载入口;新增导出 worker 命令,复用导入 worker 的部署模式。</td><td>完整附件能异步生成;崩溃恢复、重试、权限撤销、留存清理可验证。schema_version、mode、context、compatibility 等字段由服务端白名单校验。</td></tr><tr><td>P4 · 网页交互<br>估计 1–2 人日</td><td><code>frontend/src/dialogs.tsx</code>、<code>types.ts</code>、<code>api.ts</code> 按需调整:模式选择、兼容性与精度说明、任务状态、错误反馈、下载和重试。</td><td>桌面/手机可用;不显示无依据百分比;错误不丢失筛选上下文;CSV 与旧 XLSX 行为清晰保留。</td></tr><tr><td>P5 · 引擎与全量验收<br>估计 3–5 人日</td><td>新增 <code>tests/test_exporting.py</code>、扩展 <code>tests/e2e/workspace.spec.ts</code>;编写受控重算与差异报告脚本;更新 <code>docs/acceptance.md</code>。</td><td>下节所有适用门禁有可复现记录;33 万行性能验证及财务签字完成。</td></tr></tbody></table></div><p>合计粗估 <strong>10–18 人日</strong>,用于排期,不是承诺。受控 Excel 测试环境、财务确认和超预算性能优化可能增加日历时间。P1 小样本原型通过后再投入大文件任务流程;各阶段保持可单独审查和回滚。</p><p>兼容 API:旧 <code>format=xlsx</code> 默认仍为证据快照;新公式模式显式申请任务并返回任务 ID。服务端返回实际导出模式与版本,前端不凭文件后缀推断。</p></section>
<section id="tests"><h2>09 / 严格测试与上线门禁</h2><div class="notice"><strong>写入公式不等于公式算对。</strong><p>openpyxl 不执行计算;设置自动重算或 fullCalcOnLoad 也不是测试结果。必须在目标 Excel 引擎执行、保存,再同时读取公式和结果缓存验证。</p></div><div class="table-wrap"><table><thead><tr><th>测试层</th><th>必须覆盖的场景</th><th>通过标准</th></tr></thead><tbody><tr><td>结构与公式覆盖</td><td>每页、命名范围、Table、单元格类型、公式依赖、说明及数据验证;空数据导出。</td><td>衍生区域全覆盖真实公式,基础输入无意外公式;无循环引用、损坏修复提示或外部链接。</td></tr><tr><td>财务黄金样例</td><td>两种 ROI、direct/lookup 毛利、退款、负数、0、缺成本、部分缺字段、缺期、基期0、新增/消失分组。</td><td>与独立 Decimal 预期一致到批准精度;人数完全相等;缺失不能变0。</td></tr><tr><td>客户去重</td><td>同人跨科室/产品/月,重复明细、自营与非自营交集、空客户字段。</td><td>总体不相加子组人数;升单率分子去重正确;缺客户状态与系统一致。</td></tr><tr><td>真实引擎重算</td><td>Excel Windows / Mac;打开重算保存;分别读取 formula 与 data_only;修改收入、成本、原价及毛利率后再次计算。</td><td>受影响链路变化符合独立预期,非依赖指标不误变。扫描 #REF!、#DIV/0!、#VALUE!、#NAME?、#SPILL!;仅允许明确缺失状态对应的 #N/A。</td></tr><tr><td>精度极限</td><td>15位边界、24位小数、极大金额、正负抵消、舍入临界值、33万行累计差异。</td><td>精确文本不变;超出政策明确报警或拒绝;不通过放宽误差掩盖错误。</td></tr><tr><td>注入与越权</td><td>恶意标签/原始公式、工作表名特殊字符、跨组织/科室、任务 ID 猜测、下载前撤权。</td><td>无执行不可信公式、外链或敏感原值泄露;未授权下载拒绝并审计。</td></tr><tr><td>任务可靠性</td><td>重复提交、worker中断、磁盘不足、超时、并发、到期清理。</td><td>无半成品下载、孤儿文件和静默截断;失败可解释,恢复无重复发布。</td></tr><tr><td>前端与兼容回归</td><td>两模式选择、状态、错误重试、下载、移动端;现有 CSV/XLSX。</td><td>浏览器端到端通过;旧证据版仍保持精度与公式注入防护。新公式版测试只允许白名单公式,不删除旧安全断言。</td></tr><tr><td>真实附件全量</td><td>332,830行;2025-08/2026-08及原映射;全量与分组对账。</td><td>行数不缺失,金额满足政策,人数为33,147 / 38,361;缺成本 ROI 不可用,未配置自营范围不擅自补值。</td></tr></tbody></table></div><h3>发布清单(全部待实施验证)</h3><ul><li>□ 口径、精度、编辑范围、支持引擎由财务及产品负责人确认。</li><li>□ 所有指标有公式覆盖与独立数值断言,修改输入后的重算链通过。</li><li>□ 真实 Excel 重算证据包含引擎版本、脚本或步骤、输入哈希、结果与误差报告;LibreOffice 只能证明其自身兼容性。</li><li>□ 原附件全量导出、权限、安全和资源预算通过;大文件首开及改值重算满足商定目标。</li><li>□ 使用说明、列字典、异常状态与原始证据齐全,无患者原始标识泄露。</li><li>□ 灰度开关、失败回退、审计、清理、任务运行监控与运维说明就绪。</li></ul><p>上线先小范围授权用户试用公式模式,旧证据导出保留作为回退。只有 Excel 导出门禁通过,不意味着整个财务系统所有商业上线门禁自动满足。</p></section>
<section id="questions"><h2>10 / 需确认的业务决策</h2><div class="grid"><div><h3>可直接采用的工程默认</h3><ul><li>双模式并存,公式版 XLSX 不含宏和外链。</li><li>精确证据 + 数值计算 + 对账,不牺牲原始精度。</li><li>Microsoft 365 为首版公式验收目标。</li><li>固定范围、指定输入可改,结构变化重新导出。</li><li>大文件异步、授权下载、客户去标识。</li></ul></div><div><h3>上线前必须由财务确认</h3><ul><li>收入继续使用 N 列,还是另需 I 列实收口径?</li><li>舍入在每行还是最终汇总发生?使用哪种舍入规则与容差?</li><li>毛利率允许本地模拟吗?直接毛利是否允许修改?</li><li>自营产品集合、退款计人、成本归属及 ROI 口径是什么?</li><li>是否必须支持旧版 Excel/WPS,以及首次打开前就有结果缓存?</li></ul></div></div><p class="recommend"><strong>建议实施顺序:</strong>先确认口径与 Excel 版本 → 小样本真正公式与重算验证 → 33 万行任务化及性能测试 → 前端完整交互与财务签字。不要先把导出值改成数值、加几条 SUM,就标记需求完成。</p></section>
</main><footer>本文件是实施计划。现有 XLSX 导出仍为文本证据快照;本轮没有新增公式导出功能,也没有执行尚未实现功能的验收。</footer>
</body>
</html>
+36
View File
@@ -0,0 +1,36 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TraceIQ 完善项与执行路线图</title>
<style>
:root{color-scheme:light;--ink:#202725;--muted:#58645f;--line:#d8dfdc;--green:#17664f;--amber:#9a5200;--red:#a72f3d;--bg:#f5f7f6;--blue:#315d78}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.7 system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif}header{background:#fff;border-bottom:3px solid var(--green);padding:28px 20px}main,header>div,footer{max-width:1120px;margin:auto}main{padding:0 20px 40px}h1{font-size:30px;margin:4px 0 8px}h2{font-size:21px;margin:0 0 12px}h3{font-size:17px;margin:0 0 7px}.meta,.muted{color:var(--muted);font-size:13px}.notice{padding:15px 18px;margin:20px 0;background:#fff4e5;border-left:4px solid var(--amber)}section{padding:24px 0;border-bottom:1px solid var(--line)}.item{background:#fff;padding:16px 18px;margin:12px 0;border-left:4px solid var(--line)}.p0{border-color:var(--red)}.p1{border-color:var(--amber)}.p2{border-color:var(--green)}.tag{font-size:12px;font-weight:700;color:var(--muted)}table{border-collapse:collapse;width:100%;background:#fff}th,td{padding:10px 12px;border:1px solid var(--line);text-align:left;vertical-align:top}th{background:#eaf0ed}code{overflow-wrap:anywhere}footer{padding:22px 20px 36px;color:var(--muted)}@media(max-width:680px){h1{font-size:25px}table{font-size:13px}th,td{padding:8px}}
</style>
</head>
<body>
<header><div><div class="meta">TRACEIQ / 优先级核查与执行 / 2026-09-24</div><h1>完善项与执行路线图</h1><p>以当前源码、自动化测试和可访问环境为依据。测试通过不等同于业务签字或生产上线。</p></div></header>
<main>
<div class="notice"><strong>本轮基线:</strong>后端 40 passed,finance 覆盖率 86.72%(85% 门槛);隔离 SQLite Playwright 3 passed、原附件专测 1 skipped;Ruff、格式、Django system check、迁移检查、TypeScript/Vite 构建、npm audit(0 漏洞)与 pip-audit 通过。production 模式 Django <code>check --deploy</code> 零告警。Docker daemon 未运行,本机无 LibreOffice。Microsoft Excel、332,830 行公式工作簿、真实 AI/合规及商业部署仍未验收。</div>
<section><h2>P0 · 先确保验收证据可信</h2>
<article class="item p0"><div class="tag">P0.1 · 已完成 / 已复核</div><h3>维护真实的源码与验收基线</h3><p>旧文档曾错误声称 <code>tests/test_finance.py</code> 为空并把公式导出标记为未实现;当前源码有 40 项后端测试,公式工作簿、说明页、对话新增列、追问与下载均已实现。本轮路线图按当前代码、测试结果和外部门禁重建。</p></article>
<article class="item p0"><div class="tag">P0.2 · 已修复并通过专项回归</div><h3>隐藏导出任务的内部异常</h3><p>状态接口不再把 worker 异常文本发给用户,只返回通用失败提示;前端显示任务编号,数据库保留内部诊断。失败任务脱敏、临时文件删除及状态访问专项 8 passed。</p></article>
<article class="item p0"><div class="tag">P0.3 · 本机生产配置检查通过</div><h3>验证 production 部署安全配置</h3><p>production 模式、有效测试密钥、受信 HTTPS 代理下 <code>manage.py check --deploy</code> 零告警。真实域名、TLS 终止及代理头行为仍需部署环境验收。</p></article>
<article class="item p0"><div class="tag">P0.4 · 外部目标引擎</div><h3>Microsoft Excel 公式重算与兼容验收</h3><p>目标 Excel Windows/Mac 打开、重算、保存并核对公式及缓存;覆盖缺期、零分母、退款/负值、ROI、毛利来源和输入修改依赖。LibreOffice/openpyxl 不能替代目标 Excel 证据。</p></article>
<article class="item p0"><div class="tag">P0.5 · 真实数据与资源基准</div><h3>332,830 行完整公式工作簿</h3><p>公式导出当前限制 100,000 行/200 组。用原附件和可靠 PostgreSQL 验证行数、金额、人数、耗时、峰值内存、文件大小及 Excel 首开/重算;未完成前保持显式拒绝,不静默截断或放宽上限。</p></article>
<article class="item p0"><div class="tag">P0.6 · 外部业务/安全责任人</div><h3>财务口径、真实 AI 与商业发布批准</h3><p>签署实际收入与实收、退款、成本、毛利、ROI、自营集合及舍入规则;审批外部模型数据处理/出境并演练故障;完成生产密钥、TLS、备份恢复、SLA、渗透测试和商业许可证核验。审批前 AI 保持关闭。</p></article>
</section>
<section><h2>P1 · 代码层可靠性与可用性</h2>
<article class="item p1"><div class="tag">P1.1 · Docker daemon 未运行</div><h3>镜像与 Compose 运行验收</h3><p>Docker CLI 可用但 daemon 不可连接,本机暂不能构建或启动。daemon 可用后验证镜像、健康检查、worker、清理服务与重启恢复;远端 CI 需仓库平台实际触发。</p></article>
<article class="item p1"><div class="tag">P1.2 · 产品范围待确认</div><h3>自定义指标定义保存与复用</h3><p>定义当前只用于当次工作簿,不持久化到主分析页或跨会话定义库。需明确个人/组织共享、版本审批、删除和审计规则,再开发持久化。</p></article>
<article class="item p1"><div class="tag">P1.3 · 需产品确认后开发</div><h3>大数据与高基数交互</h3><p>当前汇总按请求返回分组、证据使用分页;AG Grid SSRM/Pivot/Tree Data 等计划功能尚未实现。先以目标数据规模和典型交互决定是否投入服务端行模型,避免未经验证引入商业授权与运维负担。</p></article>
</section>
<section><h2>P2 · 范围扩展</h2>
<article class="item p2"><div class="tag">P2.1 · 财务定义确认后</div><h3>扩展公式语言和缺失策略</h3><p>当前白名单仅支持现有指标/常数和加减乘除,最大 8 层;不接受任意 Excel 文本、字段引用、跨明细新聚合、按零替代或跳过缺失。每项扩展需独立财务黄金样例、注入测试和公式重算验证。</p></article>
<article class="item p2"><div class="tag">P2.2 · 目标明确后</div><h3>分析及工作簿操作增强</h3><p>可评估历史分位异常、告警、证据期间切换、明细表结构变更后的公式扩展、模板版本和工作簿内定义管理;需先给出场景和验收指标。</p></article>
</section>
<section><h2>本轮执行结果</h2><table><thead><tr><th>项目</th><th>结果</th><th>剩余门禁</th></tr></thead><tbody><tr><td>源码与路线图基线</td><td>已完成;纠正文档过时状态</td><td>以当前代码/测试为准</td></tr><tr><td>导出错误脱敏</td><td>8 项专项后端测试通过</td><td>内部诊断仅保留服务端</td></tr><tr><td>Production deploy checks</td><td>零告警</td><td>真实域名、TLS/代理验收</td></tr><tr><td>全量本机回归</td><td>40 passed / 86.72%;Playwright 3 passed、1 skipped</td><td>原附件场景需配置隔离数据集</td></tr><tr><td>商业发布门禁</td><td>尚未通过</td><td>Excel、真实规模、业务/AI审批、容器和灾备</td></tr></tbody></table></section>
<section><h2>发布判定原则</h2><p>本地质量门禁全部通过,只证明自动化覆盖范围内的代码状态。商用发布还需要 Microsoft Excel 结果、真实规模资源记录、财务口径签字、AI 数据处理批准和目标基础设施安全/灾备验证。任何一项未满足时,状态保持“未完成发布验收”。</p></section>
</main><footer>本文件按核查日建立,执行结果以随后实际运行的命令和目标环境记录更新。</footer>
</body>
</html>
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>财务 Agent 改进路线图</title>
<style>
:root{color-scheme:light;--ink:#202725;--muted:#58645f;--line:#d8dfdc;--green:#17664f;--amber:#9a5200;--red:#a72f3d;--bg:#f5f7f6}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.75 system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif}header{background:#fff;border-bottom:3px solid var(--green);padding:28px 20px}main,header>div,footer{max-width:1080px;margin:auto}main{padding:0 20px 36px}h1{font-size:30px;margin:4px 0 8px}h2{font-size:21px;margin:0 0 12px}h3{font-size:17px;margin:0 0 8px}p{margin:8px 0}.meta{color:var(--muted);font-size:13px}.status{padding:14px 18px;margin:20px 0;background:#fff4e5;border-left:4px solid var(--amber)}section{padding:24px 0;border-bottom:1px solid var(--line)}.item{padding:16px 18px;margin:12px 0;background:#fff;border-left:4px solid var(--line)}.p0{border-color:var(--red)}.p1{border-color:var(--amber)}.p2{border-color:var(--green)}.tag{font-size:12px;font-weight:700;color:var(--muted)}table{border-collapse:collapse;width:100%;background:#fff}th,td{padding:10px 12px;border:1px solid var(--line);text-align:left;vertical-align:top}th{background:#eaf0ed}code{overflow-wrap:anywhere}footer{padding:22px 20px 36px;color:var(--muted)}@media(max-width:640px){h1{font-size:25px}table{font-size:13px}th,td{padding:8px}}
</style>
</head>
<body>
<header><div><div class="meta">TRACEIQ / 工程质量与产品改进 / 2026-09-24</div><h1>财务 Agent 改进路线图</h1><p>按财务正确性、测试可信度、业务覆盖和发布风险排序;实现状态与验收状态分开记录。</p></div></header>
<main>
<div class="status"><strong>当前结论:</strong>对话新增指标、缺项追问、白名单公式编译与公式工作簿已实现;本轮专项后端 6 项、Ruff、前端类型检查及生产构建通过。生产发布仍被空的历史测试源码、公式引擎重算、真实附件规模和财务/AI 合规审批阻断。</div>
<section><h2>P0 · 发布阻断</h2>
<article class="item p0"><div class="tag">P0.1 · 阻断中</div><h3>恢复完整源码测试基线</h3><p><code>tests/test_finance.py</code> 当前为 0 字节,导致既有财务、权限、导入、分析与公式导出回归测试缺失。先从可靠备份恢复,再运行 pytest、Ruff、Django、迁移、生产构建及 Playwright。旧 .pyc 的 69 passed、1 failed、1 skipped 使用旧断言,不是当前源码验收证据。</p></article>
<article class="item p0"><div class="tag">P0.2 · LibreOffice 自定义公式与缓存已验证;Excel 待验</div><h3>公式/缓存一致性验证</h3><p>人数逻辑使用 CustomerRoster + <code>COUNTIFS</code>。本轮从当前源码生成基础及新增列工作簿,交由 LibreOffice 重算后读取;含自定义列的文件保留 136 个公式单元格,自定义“收入成本差”公式缓存及汇总引用缓存均为 2,000。仍需补足缺失期、零分母及负值等边界对账,并在 Microsoft Excel 桌面版复验。</p></article>
<article class="item p0"><div class="tag">P0.3 · 待目标环境</div><h3>Microsoft Excel Windows/Mac 验收</h3><p>在目标桌面 Excel 打开、强制重算、保存,读取公式和结果缓存;覆盖缺期、零人数、退款/负数、两种 ROI、毛利来源及编辑金额后的依赖变化。</p></article>
<article class="item p0"><div class="tag">P0.4 · 范围阻断</div><h3>332,830 行附件全量导出与资源预算</h3><p>当前上限 100,000 行/200 组。用原映射和可靠 PostgreSQL 验证完整导出、行数/金额/人数对账、耗时、峰值内存、文件体积及 Excel 首开/重算;未经实测不放宽限制,不静默截断。</p></article>
<article class="item p0"><div class="tag">P0.5 · 外部决策</div><h3>财务口径与 AI 合规</h3><p>签署实际收入/实收、退款、成本归属、毛利、ROI、自营范围和舍入口径;完成外部模型联调、隐私/数据出境审批及故障演练。批准前保持外部 AI 关闭。</p></article>
</section>
<section><h2>P1 · 可靠性与运行质量</h2>
<article class="item p1"><div class="tag">P1.1 · 已实现;专项 3 项通过</div><h3>过期工作簿与孤儿临时文件清理</h3><p>新增 <code>cleanup_formula_exports</code> 管理命令和 Compose 常驻清理服务。仅清理过期成品及超过 24 小时的临时文件,限制导出根目录,跳过符号链接;清理异常保留重试线索。已覆盖过期文件、临时文件年龄和目录外路径测试。</p></article>
<article class="item p1"><div class="tag">P1.2 · 功能实现;单测及新增列 E2E 通过</div><h3>对话定义新增汇总列并导出公式</h3><p>用户可描述列名、含义、计算、范围及缺失/零分母策略;缺项时模型必须追问,确认后服务端只接受白名单表达式树并编译为 Excel 公式。工作簿包含汇总及自定义指标页、使用说明和对账页。专项单测覆盖追问、表达式拒绝与公式输出;本轮 Playwright 已验证登录、字段导入、缺项追问、补充确认、工作簿生成和下载。</p></article>
<article class="item p1"><div class="tag">P1.3 · 待目标环境</div><h3>部署、安全与灾备验收</h3><p>完成镜像构建、TLS、数据库认证、备份恢复和 RPO/RTO 演练、并发/SLA 测试、渗透测试、密钥轮换、审计告警及商用依赖许可证核查。</p></article>
</section>
<section><h2>P2 · 产品能力扩展</h2>
<article class="item p2"><div class="tag">P2.1</div><h3>已签口径下补充分析能力</h3><p>多收入字段与消费比率、生效期毛利率、退款切换、结构占比、历史异常阈值和告警投递。</p></article>
<article class="item p2"><div class="tag">P2.2</div><h3>自定义指标定义复用</h3><p>定义保存/版本与差异审阅;新运算符、聚合或缺失策略须通过白名单、独立财务样例和安全审查。</p></article>
<article class="item p2"><div class="tag">P2.3</div><h3>工作簿及跨平台体验</h3><p>证据期间切换、平板与无障碍优化、可读的公式错误状态、更多电子表格引擎兼容验证。</p></article>
</section>
<section><h2>完成门禁</h2><table><thead><tr><th>门禁</th><th>证据</th><th>状态</th></tr></thead><tbody>
<tr><td>源码测试</td><td>恢复原测试文件并完整执行</td><td>阻断:源码缺失</td></tr>
<tr><td>静态与构建</td><td>Ruff、Django、迁移、前端构建</td><td>本轮独立复跑通过;源码恢复后仍需联跑</td></tr>
<tr><td>网页工作流</td><td>新增指标、桌面、手机 Playwright</td><td>3 项通过,1 项原附件全量场景按配置跳过</td></tr>
<tr><td>公式重算</td><td>当前版本 LibreOffice 与 Microsoft Excel</td><td>LibreOffice 自定义公式重算/缓存通过;边界样例与 Excel 待验</td></tr>
<tr><td>真实规模</td><td>原附件全量导出与资源报告</td><td>待验;当前上限 100,000 行</td></tr>
<tr><td>商业发布</td><td>财务签字、AI 合规、安全与灾备</td><td>待外部审批/目标环境</td></tr>
</tbody></table></section>
</main><footer>执行顺序:P0.1 → P0.2 → P0.3/P0.4 → P0.5 → P1 → P2。外部环境和审批不可用时保留为明确门禁,不以模拟结果替代验收。</footer>
</body>
</html>
+44
View File
@@ -0,0 +1,44 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TraceIQ 财务 Agent 改进路线图</title>
<style>
:root{color-scheme:light;--ink:#202725;--muted:#58645f;--line:#d8dfdc;--green:#17664f;--amber:#9a5200;--red:#a72f3d;--bg:#f5f7f6}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.7 system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif}header{background:#fff;border-bottom:3px solid var(--green);padding:26px 20px}header>div,main,footer{max-width:1080px;margin:auto}main{padding:0 20px 36px}h1{font-size:30px;margin:4px 0 8px}h2{font-size:21px;margin:0 0 12px}h3{font-size:17px;margin:0 0 8px}p{margin:8px 0}.meta,.tag{color:var(--muted);font-size:13px}.status{padding:14px 18px;margin:20px 0;background:#fff4e5;border-left:4px solid var(--amber)}section{padding:22px 0;border-bottom:1px solid var(--line)}.item{padding:15px 18px;margin:12px 0;background:#fff;border-left:4px solid var(--line)}.p0{border-color:var(--red)}.p1{border-color:var(--amber)}.p2{border-color:var(--green)}.tag{font-weight:700}table{border-collapse:collapse;width:100%;background:#fff}th,td{padding:9px 11px;border:1px solid var(--line);text-align:left;vertical-align:top}th{background:#eaf0ed}code{overflow-wrap:anywhere}footer{padding:22px 20px 36px;color:var(--muted)}@media(max-width:640px){h1{font-size:25px}table{font-size:13px}th,td{padding:7px}}
</style>
</head>
<body>
<header><div><div class="meta">TRACEIQ / 工程质量与产品改进 / 2026-09-24</div><h1>财务 Agent 改进路线图</h1><p>依据当前仓库和本轮实测重排;实现状态、外部验收与生产资格分别记录。</p></div></header>
<main>
<div class="status"><strong>当前结论:</strong>公式导出审查已修复文本条件、未分类对账、公式注入、任务路径、文件权限与失败恢复问题,并改为流式写入;后端 61 passed、finance 覆盖率 87.66%,LibreOfficeDev 公式重算共 4 项通过。100,000 行产品上限实测峰值 RSS 约 136.4 MB。Microsoft Excel 实机、原附件 332,830 行范围方案、真实 AI/财务审批和目标环境验收仍未完成,不能认定具备生产商用资格。</div>
<section><h2>P0 · 正确性与发布阻断</h2>
<article class="item p0"><div class="tag">P0.1 · 本机 LibreOffice 回归通过</div><h3>公式重算建立可重复黄金测试</h3><p>当前共 4 项 LibreOfficeDev 重算测试:test_formula_recalculation.py 3 项、test_formula_recalculation_gross.py 1 项,覆盖自定义汇总及变化率、明细收入编辑联动、零成本 ROI、缺失基期及 direct/lookup 毛利来源。它们只证明这些具体样例在 LibreOffice 中的结果,不代表 Microsoft Excel 兼容或财务签字。</p></article>
<article class="item p0"><div class="tag">P0.2 · 目标环境门禁</div><h3>Microsoft Excel Windows / Mac 实机验收</h3><p>本机曾以 Microsoft Excel 打开测试工作簿,公式栏确认汇总公式包含 COUNTIFS / SUMIFS;但 Excel 显示只读(View Only / 需激活 Microsoft 365),无法保存重算副本,且检查到的样例分组为 Test、与预期不匹配。故仅有“公式可见”的证据,Excel 重算结果、缓存和业务样例均未验收。后续须在可编辑的目标 Windows/Mac Excel 中用受控正确样例强制重算、保存,并核验函数兼容、数据表引用、错误单元格和输入修改依赖链。</p></article>
<article class="item p0"><div class="tag">P0.3 · 100,000 行产品上限已优化并实测</div><h3>流式公式工作簿与原附件范围决策</h3><p>公式版本 3 已将所有工作表改为 openpyxl write-only 顺序写入,同时保留 Data 与 CustomerRoster 表格、结构化引用、说明、证据和对账。隔离 SQLite 合成基准:20,000 行 5.26 秒、3.27 MB、峰值 RSS 77.9 MB;100,000 行 25.96 秒、16.22 MB、峰值 RSS 136.4 MB,ZIP/OOXML 完整性及公式读取通过。生产限制仍为 100,000 行/200 组;真实附件 332,830 行不在当前产品范围,下一步必须选择可审计分卷或明确提高上限后再做原附件流式资源、打开和重算验收。</p></article>
<article class="item p0"><div class="tag">P0.4 · 财务审批</div><h3>冻结收入、退款、毛利及 ROI 口径</h3><p>由财务负责人签署 N 列实际收入与 I 列实收、原价、退款、成本归属、毛利率、自营产品集、升单定义与舍入精度。原附件成本全缺,ROI 应维持不可用;不得以技术测试替代业务签字。</p></article>
<article class="item p0"><div class="tag">P0.5 · 隐私 / 模型外部审批</div><h3>外部 AI 真实联调与数据处理审批</h3><p>在批准前保持 AI 关闭。审批后验证模型版本、超时、限流、拒答、审计脱敏、数据处理与出境依据;模型只提出列定义,服务端继续严格校验白名单表达式并要求用户确认。</p></article>
</section>
<section><h2>P1 · 商用运维与可恢复性</h2>
<article class="item p1"><div class="tag">P1.1 · 本地待执行 / 环境受限</div><h3>Docker 镜像与生产 Compose 验收</h3><p>本轮完整生产变量下 Django <code>check --deploy</code> 无告警,依赖审计为零已知漏洞;Docker daemon 当前不可连接,镜像构建尚未验证。daemon 恢复后构建镜像、运行迁移和健康检查,确认非 root、只读根文件系统、卷权限及 worker。</p></article>
<article class="item p1"><div class="tag">P1.2 · 目标环境门禁</div><h3>备份恢复、并发和安全运营</h3><p>验收 TLS、密钥轮换、最小权限、加密备份及恢复 RPO/RTO、队列积压/失败告警、访问日志脱敏、容量阈值、并发 SLA 和独立安全审查;AG Grid Enterprise 使用前确认商业许可。</p></article>
<article class="item p1"><div class="tag">P1.3 · 部分已实现;范围受限</div><h3>对话定义新增汇总列并导出公式</h3><p>用户可描述列名、含义、计算、适用范围及缺失处理;信息不全时追问并结合完整对话复核。公式只使用数据集当前可计算的既有指标与白名单运算,服务端再次校验数据映射;确认后写入公式工作簿并带说明。任意 Excel 函数、跨明细新聚合、定义保存复用及导出后自动扩行未实现。</p></article>
</section>
<section><h2>P2 · 扩展能力</h2>
<article class="item p2"><div class="tag">P2.1</div><h3>签字口径下扩展分析</h3><p>多收入字段与消费比率、生效期毛利率、退款策略、结构占比、历史异常阈值和告警投递。</p></article>
<article class="item p2"><div class="tag">P2.2</div><h3>跨平台与辅助功能</h3><p>补齐平板、键盘/屏幕阅读器、证据期间切换和目标表格软件兼容矩阵;Web 可复用不等同于 Excel 文件跨引擎兼容。</p></article>
</section>
<section><h2>本轮证据</h2><table><thead><tr><th>项目</th><th>结果</th><th>边界</th></tr></thead><tbody>
<tr><td>后端及覆盖率</td><td>61 passed;finance 87.66%</td><td>SQLite 测试;包含流式工作簿、公式语义、注入防护、任务路径/权限/恢复及 LibreOffice 重算;未替代 PostgreSQL CI</td></tr>
<tr><td>LibreOffice 公式重算</td><td>共 4 项通过(test_formula_recalculation.py 3 项、test_formula_recalculation_gross.py 1 项),direct/lookup 毛利来源测试包含在这 4 项内</td><td>LibreOfficeDev;Microsoft Excel 仅确认公式可见,未完成可保存重算验收</td></tr>
<tr><td>流式容量基准</td><td>100,000 行:25.96 秒、16.22 MB、峰值 RSS 136.4 MB;20,000 行:5.26 秒、3.27 MB、峰值 RSS 77.9 MB</td><td>隔离 SQLite 合成数据,本机单次测量;生产上限保持 100,000 行,不能替代目标环境并发 SLA</td></tr>
<tr><td>浏览器回归</td><td>3 passed,1 skipped</td><td>跳过需显式指定附件的原附件 E2E</td></tr>
<tr><td>构建 / 静态检查</td><td>Ruff、Prettier、TypeScript/Vite、Django check、迁移检查通过</td><td>依赖审计报告 0 个已知漏洞;不等于渗透测试</td></tr>
<tr><td>生产配置检查</td><td>完整临时生产配置下 <code>check --deploy</code> 无告警</td><td>不代表目标基础设施上线验收</td></tr>
<tr><td>Compose / Docker</td><td>未通过</td><td>仓库无真实 .env;Docker daemon 未运行,未构建镜像</td></tr>
<tr><td>Excel / 原附件公式</td><td>Excel 打开样本并确认公式存在;PostgreSQL 对账完成;旧非流式版本曾生成 332,830 行</td><td>Excel 只读,无法保存重算副本;所见分组与预期不匹配。原附件超过 100,000 行产品上限,公式版本 3 尚未对 332,830 行做越界放宽测试</td></tr>
</tbody></table></section>
<section><h2>执行顺序与完成规则</h2><p>顺序:维护 P0.1 黄金重算 → P0.2 Microsoft Excel → P0.3 资源优化 → P0.4 / P0.5 外部审批 → P1 → P2。本轮补齐了可重复的金额编辑、零成本与缺失基期重算测试,并复核新增列映射保护。LibreOffice 不替代 Excel,财务/AI 审批和目标基础设施测试需对应责任方及环境。</p><p>测试必须覆盖代码实际行为;每项门禁记录日期、环境、版本、样例、结果和限制。不能用 mock、静态公式存在或 build 通过声称生产已验收。</p></section>
</main><footer>路线图是执行与验收记录,不是生产准入授权。详见 <a href="acceptance.md">验收状态与上线门禁</a>。</footer>
</body>
</html>
+77
View File
@@ -0,0 +1,77 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>财务 Agent:剩余问题与修复清单 · 2026-09-26</title>
<style>
:root{color-scheme:light;--ink:#202925;--muted:#57635d;--line:#d7dfda;--green:#17664f;--red:#a52b40;--amber:#875408}*{box-sizing:border-box}body{margin:0;background:#f7f9f8;color:var(--ink);font:15px/1.8 system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;letter-spacing:0}header{background:#fff;border-bottom:3px solid var(--green);padding:32px 22px}header>div,main,footer{max-width:1120px;margin:auto}main{padding:0 22px 40px}h1{font-size:30px;line-height:1.4;margin:8px 0}h2{font-size:23px;margin:0 0 14px}h3{font-size:18px;margin:0 0 10px}p{margin:8px 0}small,.muted{color:var(--muted)}nav{display:flex;flex-wrap:wrap;gap:10px 22px;padding:18px 0}a{color:var(--green);text-underline-offset:3px}section{padding:25px 0;border-bottom:1px solid var(--line)}article{padding:18px 0;border-top:1px solid var(--line)}article:first-of-type{border-top:0}.notice{padding:16px 20px;border-left:4px solid var(--amber);background:#fff4de;margin:20px 0}.critical{border-color:var(--red);background:#fff0f1}.ok{color:var(--green)}.p0{color:var(--red)}.p1{color:var(--amber)}.tag{font-size:13px;font-weight:700}table{width:100%;border-collapse:collapse;background:#fff}th,td{padding:11px;border:1px solid var(--line);text-align:left;vertical-align:top;overflow-wrap:anywhere}th{background:#eaf0ed}ul,ol{padding-left:23px}li{margin:6px 0}code{font-size:13px;overflow-wrap:anywhere}pre{white-space:pre-wrap;background:#edf1ef;padding:14px;overflow-wrap:anywhere}.table-wrap{overflow-x:auto}footer{padding:24px 22px;color:var(--muted)}@media(max-width:640px){h1{font-size:25px}h2{font-size:21px}main{padding-inline:16px}th,td{padding:8px;font-size:13px}.table-wrap table{min-width:650px}}@media print{body{background:#fff}nav{display:none}section,article{break-inside:auto}h2,h3{break-after:avoid}.table-wrap{overflow:visible}a{color:inherit}header{padding:10px 0}main{padding:0}.notice{border:1px solid #777}}
</style>
</head>
<body>
<header><div><small>TRACEIQ / 工程现状与发布门禁 / 2026-09-26 / Asia/Singapore</small><h1>财务 Agent:剩余问题与修复清单</h1><p>面向下一轮开发、财务验收及生产部署。按当前源码和最近完成的测试记录整理,不将历史计划或测试通过等同于商用准入。</p></div></header>
<main>
<nav aria-label="报告目录"><a href="#summary">结论</a><a href="#baseline">已完成与测试</a><a href="#bugs">需要修复的代码问题</a><a href="#gaps">剩余功能</a><a href="#gates">外部门禁</a><a href="#sequence">推荐顺序</a><a href="#acceptance">验收清单</a></nav>
<section id="summary"><h2>一、结论与阅读方式</h2>
<div class="notice critical"><strong>目前不能认定达到生产环境商用标准。</strong><p>公式导出、说明页、对话追问、新增公式列、个人定义保存复用与证据分页已经实现;仍有需要修复的安全/交互边界、未完成的产品能力,以及必须在目标 Excel、数据库、基础设施和业务审批环境关闭的门禁。</p></div>
<p><strong>本次交付仅新增本报告,不修改业务代码、不执行新的数据库迁移。</strong>以下“已完成”包括此前连续开发完成的改动;“静态确认”指源码可直接看出的行为,尚未新增专项复现测试,不能冒充测试复现结果。</p>
<ul><li><strong>P0:</strong>影响敏感文件安全、核心财务正确性或生产准入,正式上线前必须关闭。</li><li><strong>P1:</strong>影响日常操作可靠性、可解释性、协作和可维护性,应在受控试用前或紧接其后完成。</li><li><strong>P2:</strong>扩展能力,按合同范围和真实业务优先级开发,不因存在依赖或设计稿就视为已实现。</li></ul>
</section>
<section id="baseline"><h2>二、当前已经完成什么</h2>
<div class="table-wrap"><table><thead><tr><th>能力</th><th>已完成状态</th><th>不能据此推断的内容</th></tr></thead><tbody>
<tr><td>公式工作簿</td><td>版本 3,流式生成计算明细、汇总、使用说明、参数口径、人数去重、原始证据、对账;有自定义列时增加自定义指标页。</td><td>不是任意 Excel 模板生成器;不是全部输入/结构变化都能正确重算。</td></tr>
<tr><td>对话新增列</td><td>描述不全时追问,补充后确认;服务端校验表达式树及数据映射可用性。支持既有指标、常数、加减乘除。</td><td>真实外部模型未完成联调;自然语言适用范围不等于执行任意筛选、聚合规则。</td></tr>
<tr><td>个人定义库</td><td>按用户与数据集隔离,保存、同名更新、列出、载入、删除;保存和导出时校验;迁移文件 0004 已存在,隔离测试库已执行。</td><td>不是团队共享定义库;没有草稿续聊、版本审批、并发编辑冲突保护。非测试环境是否迁移仍需核对。</td></tr>
<tr><td>证据与文件导出</td><td>本期/基期切换、每页 50 条及翻页;CSV/XLSX 证据以临时文件和 FileResponse 分块发送;金额文本和公式注入防护保留。</td><td>前端仍用 Blob 接收完整下载文件;临时磁盘/tmpfs、并发容量尚无生产 SLA。</td></tr>
<tr><td>导出可靠性</td><td>任务专属路径、0600 文件与 0700 目录、失败状态恢复、随机临时文件、授权范围检查、过期清理。</td><td>并非所有符号链接异常路径都安全,见 F01;也未完成磁盘故障及生产崩溃恢复演练。</td></tr>
</tbody></table></div>
<h3>最近完整测试记录</h3>
<ul><li><strong>后端:65 passed,95.12 秒;finance 覆盖率 87.63%,85% 门槛通过。</strong>SQLite 测试,包含定义库及导出回归。</li><li><strong>真实公式重算:4 项 LibreOffice 测试通过。</strong>覆盖自定义汇总、变化率、金额编辑联动、零成本、缺基期和 direct/lookup 毛利。不能替代 Microsoft Excel 实机。</li><li><strong>浏览器:3 passed,1 skipped,24.7 秒。</strong>新隔离数据库,覆盖追问、保存定义、关闭重开、复用后生成,另含桌面、手机、证据翻页及下载。AI 响应采用 mock;分页第 51 条交互使用 mock 响应,后端分页另有 API 测试。</li><li>跳过项:未设置 <code>REFERENCE_DATASET_NAME</code> 的原附件全量 UI 用例,不属于通过项。</li><li>此前已通过 Ruff lint/format、TypeScript/Vite、Django check、迁移一致性检查;2026-09-24 的 npm 生产依赖审计与 pip-audit 为零已知漏洞。这些不是本报告生成时重新运行的结果。</li><li>历史合成容量基准:100,000 行生成 25.96 秒,产物约 16.22 MB,峰值 RSS 约 136.4 MB;单机单次、非并发、非目标 Excel 重算性能。</li></ul>
<p class="muted">现有 acceptance.md / improvement-roadmap.html 仍存在 61 项测试、“没有定义库”等旧表述;历史 Excel 计划也有相互矛盾的状态提示。当前状态以本报告与最近完成的实测为准,后续应统一维护单一验收入口。</p>
</section>
<section id="bugs"><h2>三、需要继续修复的代码问题</h2>
<article><div class="tag p0">F01 · P0 · 静态确认 · 文件安全</div><h3>失败清理可能沿符号链接父目录删除非任务文件</h3><p><strong>位置:</strong><code>finance/exporting.py → process_formula_export()</code>。先设置 target,再检查 target.parent 是否为符号链接;拒绝后进入异常分支,仅检查 path.is_symlink(),未检查父目录。父目录为链接而最终文件本身为普通文件时,unlink 会跟随父目录删除链接目标下同名文件。</p><p><strong>影响:</strong>需要本地存储目录被操纵这一前提,不能描述为普通远程用户已可利用;但违背“异常清理只删除自己创建的文件”的边界。</p><p><strong>推荐修复:</strong>路径完整验证前不要将目标登记为可清理文件;只清理本次实际创建、且位于受控目录中的文件,必要时用目录描述符及不跟随链接的文件操作。不要用失败清理代替旧孤儿文件回收。</p><p><strong>验收:</strong>父目录链接到受保护目录,预置同名文件;执行必须失败且受保护文件字节不变,任务为 failed;覆盖根目录链接、目标链接、写盘失败与正常重试。</p></article>
<article><div class="tag p1">F02 · P1 · 静态确认 · 故障清理</div><h3>清理失败被忽略,敏感孤儿文件缺少回收路径</h3><p><strong>位置:</strong><code>finance/exporting.py</code> 与 <code>cleanup_formula_exports.py</code>。异常清理吞掉 OSError 后清空 job.path;清理器主要处理已成功且过期的文件及旧 .tmp,失败任务残留 .xlsx 可能不再被追踪。</p><p><strong>修复:</strong>记录不含敏感数据的清理失败日志及任务编号,为安全范围内的孤儿 .xlsx 制定保留期与回收规则;不要删除仍处于活动任务的文件。</p><p><strong>验收:</strong>注入 unlink 权限错误,任务失败状态仍保存;可观察到告警,恢复权限后回收成功,其他任务文件不受影响。</p></article>
<article><div class="tag p1">F03 · P1 · 静态确认 · 证据弹窗</div><h3>重复点击当前期间可能让已加载列表停在“加载中”</h3><p><strong>位置:</strong><code>frontend/src/dialogs.tsx → EvidenceDialog.selectSide()</code>。第 0 页点击当前已选期间会清空 result,但 side/page 没变化,依赖这些值的 effect 不会重新请求。</p><p><strong>修复:</strong>同期间同页直接返回,或明确触发刷新;补加载、空集、失败重试状态。</p><p><strong>验收:</strong>当前期间重复点击、快速本期/基期切换、第二页切期间、空列表和请求失败均不显示过期数据或永久加载。</p></article>
<article><div class="tag p1">F04 · P1 · 静态确认 · 定义复用后的对话</div><h3>载入已保存定义后追问,没有把原定义带给模型</h3><p><strong>位置:</strong><code>FormulaExportDialog.loadDefinition()/send()</code>。载入定义会清空 messages,随后只发送新增描述;“把刚才公式改成乘以 100”之类指代不能可靠关联已载入表达式。</p><p><strong>修复:</strong>在可见、经同意的对话上下文中明确附带原定义,或建立服务端定义引用;仍要求重新确认,不让旧定义静默覆盖新解释。选择空选项也应同步清理当前定义,避免选择状态与预览不一致。</p><p><strong>验收:</strong>保存 A、重开载入 A、发送依赖 A 的修改,检查模型请求实际包含 A;未发送补充时禁止生成,修改后生成的公式符合新定义。</p></article>
<article><div class="tag p1">F05 · P1 · 静态确认 · 定义库并发与审计</div><h3>50 条上限不是原子约束,同名更新没有冲突检测</h3><p><strong>位置:</strong><code>finance/formula_views.py → formula_definitions()</code>。先 count 再 update_or_create,并发不同名字可能突破上限;同名更新采用最后写入覆盖,未携带 revision。保存/删除与审计也不在同一外层事务内。</p><p><strong>修复:</strong>事务内锁定稳定的用户/数据集所属行,原子检查配额;引入 revision 和 409 冲突响应;变更和审计一同提交,保存增加合理限流。前端明确同名更新行为。</p><p><strong>验收:</strong>PostgreSQL 并发保存不能产生第 51 条;两个标签页更新不静默丢失;模拟审计写入失败后定义变更回滚。</p></article>
<article><div class="tag p1">F06 · P1 · 静态确认 · 工作簿可解释性</div><h3>“产品毛利率可编辑”说明与实际公式引用不一致</h3><p><strong>位置:</strong><code>finance/exporting.py → 参数与口径 / GrossCalc</code>。参数页毛利率写成字典文本并标为可编辑,实际明细公式引用每行 MarginRate,修改参数页文本不会联动。说明页还提到“本页分组维度”,但没有完整的维度键与显示名称字典。</p><p><strong>推荐:</strong>近期明确参数页为只读快照,写清需要修改计算明细的哪类输入;如必须按产品统一模拟,则实现真实产品毛利率参数表与 lookup 依赖,并验证 direct 毛利不受影响。</p><p><strong>验收:</strong>每个标为可编辑的输入都对应真实依赖;收入、成本、原价、直接毛利、lookup 毛利率分别改值重算,说明页列出字段、单位、来源、缺失含义和固定结构边界。</p></article>
<article><div class="tag p1">F07 · P1 · 静态确认 · 财务校验范围</div><h3>对账采用统一 0.01 阈值,自定义公式没有独立服务器参考</h3><p><strong>位置:</strong><code>finance/exporting.py → 对账检查</code>。人数、金额、比率共享差异阈值;对小数形式的比率,0.01 是一个百分点,未必适用业务。自定义列标记“需业务验收”,不是自动对账通过。</p><p><strong>修复:</strong>财务批准后按指标配置比较规则:人数严格相等、金额按币种和舍入精度、比率独立阈值;用 Decimal 白名单表达式解释器计算自定义指标参考,不能执行任意代码。保持原始金额文本不变。</p><p><strong>验收:</strong>阈值边界、大数、抵消、极小值、除零、缺失和多层表达式独立黄金样例通过;不得为消除报错而放宽容差。</p></article>
<article><div class="tag p1">F08 · P1 · 验证缺口 · 权限撤销与任务生命周期</div><h3>执行/下载阶段需要覆盖角色撤销、超时与崩溃恢复</h3><p>当前有组织、任务所有者、科室范围检查,但 worker 不重新要求 admin/analyst 角色;下载接口也未声明同创建接口的角色白名单。是否允许被降为 viewer 的账号下载旧导出,需要明确政策,不能默认授权语义已完整。</p><p><strong>推荐:</strong>敏感公式工作簿在申请、执行、下载时统一核验角色、组织、账户有效性和科室;补任务超时、重复请求、过期下载、worker 发布后崩溃的测试及运维告警。</p><p><strong>验收:</strong>排队后撤权、成功后撤权均按签署政策处理;半成品不能下载;重启不重复发布或无限停留 processing。生产 PostgreSQL 锁语义单独验证。</p></article>
</section>
<section id="gaps"><h2>四、尚未完成的功能与产品边界</h2>
<div class="table-wrap"><table><thead><tr><th>优先级 / 功能</th><th>当前缺口</th><th>建议与完成标准</th></tr></thead><tbody>
<tr><td>P1 · 新列出现在网页汇总表</td><td>当前新增指标主要进入导出的自定义指标页,并未成为主分析表持久化可计算列。</td><td>若原需求包含网页表格,需新增受控服务器计算、列选择与展示;网页结果、导出公式、Decimal 参考使用同一语义,缺失不转零。</td></tr>
<tr><td>P1 · 多列编辑与定义生命周期</td><td>API 最多 10 列,但对话弹窗生成时仅提交当前单列;未完成草稿续聊、版本历史、团队共享和审批。</td><td>先做当前数据集的多列列表与显式确认,后做草稿。个人定义保存复用已完成,不应重复开发。团队共享另设权限和版本策略。</td></tr>
<tr><td>P1 · 适用范围与表达式能力</td><td>scope 为说明文本,实际按当前分组、本期/基期计算;不能表达任意条件、跨明细新聚合、任意 Excel 函数、维度列或其他缺失策略。</td><td>模型明确拒绝不支持范围,不用自然语言说明冒充已执行规则。扩展时结构化范围并加入服务端白名单及黄金测试。</td></tr>
<tr><td>P1 · Excel 编辑防误操作</td><td>人数辅助表、期间、身份、维度为固定快照;追加/删除明细不能保证全部汇总与去重同步。输入验证、公式保护、完整字段字典未全部实现。</td><td>首版推荐固定结构、明确可编辑金额列并防误操作;结构改变需重新导出。表保护不是加密或真正权限控制。</td></tr>
<tr><td>P1 · 原附件 332,830 行导出</td><td>当前产品仍限制 100,000 行 / 200 组;不能一次完整导出原附件。</td><td>推荐可审计分卷并保留全局汇总/去重口径,不能把分卷人数简单相加。备选是正式提高上限后验收内存、并发、Excel 首开和改值重算,不能仅改常量。</td></tr>
<tr><td>P1 · 结果缓存与大文件下载</td><td>openpyxl 不执行公式;未重算文件的预览/缓存读取可能为空。浏览器 Blob 下载完整驻留内存;生产 /tmp 为 tmpfs,临时文件仍计入容器内存。</td><td>明确必须由目标引擎重算;如需要服务器生成已缓存副本,独立评估计算引擎。大文件直接附件下载及临时存储配额需实测。</td></tr>
<tr><td>P1 · 高基数与可访问性</td><td>聚合分组全量返回;缺高基数结果窗口、平板专项、键盘/屏幕阅读器专项。浏览器自动测试不等于人工可访问性验收。</td><td>先测真实高基数与并发,再决定分页或 SSRM;补 focus、Esc 关闭、错误提示、表头关联与触控专项。</td></tr>
<tr><td>P2 · 扩展业务能力</td><td>多收入字段口径、消费比率、生效期毛利率、退款策略、结构占比、历史阈值、告警渠道和团队调查分派未完整实现。</td><td>先冻结业务定义,再逐项开发,不擅自以现有收入字段替代不同含义。</td></tr>
<tr><td>P2 · 跨平台与高级网格</td><td>已有响应式 Web,没有原生客户端;AG Grid SSRM/Pivot/Tree Data/Master-Detail 未完整接入。</td><td>Web 是复用基础,不等于原生交付。按真实需求和商业授权选择 PWA/桌面封装或高级网格。</td></tr>
</tbody></table></div>
</section>
<section id="gates"><h2>五、必须外部完成的发布门禁</h2>
<div class="table-wrap"><table><thead><tr><th>门禁</th><th>现状 / 责任方</th><th>关闭证据</th></tr></thead><tbody>
<tr><td>P0 · Microsoft Excel 实机</td><td>历史只读 Excel 仅确认公式可见,无法保存重算;样例分组也与预期不符。财务、QA、目标终端负责人。</td><td>在可编辑 Windows/Mac Excel 用受控样例打开、强制重算、保存;读取公式和结果缓存,改值后依赖链正确,无非预期错误与修复提示。</td></tr>
<tr><td>P0 · 财务签字与精度政策</td><td>原附件收入/实收定义有歧义,成本全缺;财务负责人。</td><td>签署收入、退款、原价、成本归属、毛利、ROI、自营、升单和容差。缺成本 ROI 保持不可用;不以技术测试替代业务认可。</td></tr>
<tr><td>P0 · AI 真实联调及隐私</td><td>外部响应主要以 mock 验证;对话文本与筛选标签可能包含敏感信息。合规、数据负责人、AI 服务负责人。</td><td>审批数据处理/出境、模型版本、留存策略;真实验证超时、拒答、限流、非法输出、复杂 schema 接受度。批准前保持 AI 关闭。</td></tr>
<tr><td>P0 · 目标基础设施</td><td>历史 Docker daemon 不可用、真实 .env 不存在;配置已交付,不等于构建和运行已验收。运维、安全。</td><td>目标镜像构建、迁移 0004、非 root/卷权限、TLS、代理、数据库认证、队列、备份恢复、日志脱敏、安全扫描与许可证通过。</td></tr>
<tr><td>P1 · 当前版本 PostgreSQL 与 SLA</td><td>最近 65 项全量是 SQLite;历史 PostgreSQL 对账/测试不能替代本版并发和锁语义。</td><td>在独立 PostgreSQL 执行当前测试、并发定义保存、worker 恢复、导出压力;记录 P95、资源预算、备份恢复 RPO/RTO。</td></tr>
<tr><td>P1 · 安全运营和许可</td><td>没有完整 SSO/MFA、自助找回、数据库 RLS、不可变审计和外部告警;并非所有产品必须全选,但必须作安全决策。</td><td>风险评估明确必需项;验证加密存储、密钥轮换、权限回收和安全审查;启用 Enterprise 前取得对应商业许可。</td></tr>
</tbody></table></div>
</section>
<section id="sequence"><h2>六、推荐修复顺序</h2>
<ol><li><strong>安全收尾:</strong>先 F01、F02、F08,明确文件清理边界与撤权政策,添加失败注入和越权回归。</li><li><strong>日常交互:</strong>修 F03、F04;补定义库删除、空选项、失败重试、快速切换和重复点击 E2E。</li><li><strong>持久化可靠性:</strong>修 F05,做 PostgreSQL 事务、配额和冲突测试;迁移验证应覆盖既有数据库。</li><li><strong>工作簿真实性:</strong>修 F06,完善输入/参数字典与保护;F07 的容差需先由财务确认,再增加独立数值对账。</li><li><strong>补齐原始用户目标:</strong>确认网页主汇总表也需要新列后,实现网页计算、多列选择与导出一致性;完成草稿续聊。</li><li><strong>发布前:</strong>解决原附件范围,执行 Excel、真实 AI、财务、安全、基础设施和并发验收。任何一项未关闭都保留明确限制,不标记“全功能商用完成”。</li></ol>
<p>没有给出未经测量的工期承诺。前三项主要由工程承担;财务口径、数据处理审批和目标环境依赖必须明确责任人,不能通过延长本地编码替代。</p>
</section>
<section id="acceptance"><h2>七、下一轮验收与交付清单</h2>
<ul><li>为每个修复加入“修复前失败、修复后通过”的专项断言;全量后端覆盖率不低于 85%,同时保留财务黄金样例。</li><li>安全回归包含父目录链接、文件权限、清理失败、撤权后执行/下载、同名定义并发更新与配额边界。</li><li>LibreOffice 和目标 Excel 分别记录版本、输入样例、公式、缓存结果与修改后差异,不合并为笼统的“Excel 测试通过”。</li><li>运行桌面/手机 E2E;指定隔离原附件数据集后执行目前跳过的用例。不得用真实生产账号或生产数据环境运行写入型测试。</li><li>Ruff、格式、TypeScript、构建、Django、迁移一致性、依赖审计通过;Docker/PostgreSQL 等环境受限项明确记录未执行原因。</li><li>交付更新后的测试记录、迁移说明、部署/回滚步骤、问题状态及新 HTML。保留历史基准,但标题应明确“历史”,消除多个文档的冲突状态。</li></ul>
<h3>源码与相关材料</h3>
<p><a href="../finance/exporting.py">公式生成与任务发布</a> · <a href="../finance/formula_views.py">定义库与导出 API</a> · <a href="../finance/views.py">证据导出与分页</a> · <a href="../frontend/src/dialogs.tsx">网页对话与证据交互</a> · <a href="../tests/">测试目录</a></p>
<p><a href="acceptance.md">既有验收记录(部分状态待同步)</a> · <a href="improvement-roadmap.html">历史路线图</a> · <a href="excel-formula-export-plan.html">最初 Excel 实施方案(历史设计,不代表现状)</a></p>
</section>
</main><footer>本报告不包含患者明细、凭据或真实财务原值。源码静态判断、已完成自动化测试、产品范围选择和正式生产验收分别记录;本报告不是上线授权。</footer>
</body>
</html>