编辑 | blame | 历史 | 原始文档

功能测试报告_汇总大表四页数据驱动_2026-09-13

一、功能说明

1. 背景

用户反馈:导出 2026 年 8 月《道路运输量汇总表》后,以下 4 张**跨页合成页**仍是上一报表期的静态值(标题写「2026年1-7月 / 2026年7月」,数值也是 7 月的,不随报表期变化):

页名 母版原状态
城市汇总 整页静态(1-7 月累计 + 7 月当月)
城市分市州 4 块整页静态
中口径分析 2 块整页静态
道路运输周转量 2 块整页静态

用户选定**方案 A**:沿用货运排名页的做法——用母版台账页自带的 2025 年同期列缓存值当同比基数,把「当年累计值」刷成 1-8 月(同比列沿用母版口径),4 页一次性做出来。

2. 口径(先验证、后编码)

编码前先用母版台账页逐格聚合反推四页口径,与四页成品逐格比对 0 差异后确认:

指标 口径
城市客运量 公交城市内客运量 + 巡游出租城市内客运量 + 网约车城市内客运量 + 轨道客运量 + 轮渡客运量
城市客运周转量 同上,换成各自旅客周转量
中口径客运量/周转量 公路班线包车 + 城际城乡公交 + 城际城乡巡游出租 + 城际城乡网约车,其中「城际城乡 X = X 总量 − X 城市内」(仅公交/出租/网约车;班线包车无城市内概念,直接用总量)
道路货运周转量 货运页市州「规上货物周转量 + 规下货物周转量」(**不用**母版「规上+规下」公式行)
道路运输周转量页「道路客运周转量」 班线包车周转量 + 城际城乡公交/出租/网约车周转量
同比 当期 ÷ 母版台账页 2025 年同期列 − 1

关于 2025 同期基数:库中只有 2026 年城市客运/网约车数据,没有 2025 年数据,故 2025 同期一律取**母版台账页自带的 2025 年逐月列缓存值**(V=1月、X=2月 … AJ=8月)。这也正是方案 A 的取巧点:母版台账页本身带全 2025 逐月列,无需等 2025 数据入库。

3. 实现

改动文件:traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java(+494 −2)。

  • 新增入口 refreshSummaryCumulativeSheets(XSSFWorkbook wb, int year, int month);接在导出链路的 refreshSummaryRankSheets(...) 之后、applySummaryReferenceLayout(wb) 之前调用。
  • 台账取数 smReadLedgerMetrics:**按行标签识别、不写死行号**
  • 公交/出租/网约车:每市州「客运量 / 旅客周转量 / 其中城市内客运量 / 其中城市内旅客周转量」4 行;
  • 轨道、轮渡:轨道(全省/武汉/黄石)与轮渡(全省/武汉)分块;
  • 班线包车:全省与 17 市州客运量/周转量(「其中个体」行不重复计入);
  • 货运(页名带前导空格):市州「规上货物周转量 + 规下货物周转量」。
  • 月份列:2026 年逐月列 C=1月 … Q=8月(SM_CUR_COL0=2),2025 年同期列 V=1月 … AJ=8月(SM_LAST_COL0=21),每月间隔 2 列(值列 + 同比列)。
  • 19 维指标位(SM_DIM=19):公交/出租/网约车 各 4 维(总量、周转量、城市内总量、城市内周转量)+ 轨道 2 维 + 轮渡 2 维 + 班线包车 2 维 + 货运周转量 1 维。
  • 写值规则 smSetVal:**目标格原本是公式 → 保留母版公式不覆盖**(打开即重算);目标格为空且新值为 0 → 不新增;其余先 setBlank() 再写,避免 inlineStr 残留。
  • 四页实际写入 1056 格。

二、测试环境

  • 后端 http://localhost:8090(start-dev.ps1 启动,PID 27840),前端 http://localhost:8080(PID 23416)均就绪。
  • 母版:docs/生成汇总大表/2026年8月道路运输量汇总表.xlsx;版式参照:docs/生成汇总大表/生成_道路运输量汇总表.xlsx。
  • 导出接口:GET /api/report/export/summaryWorkbook?period=YYYY-MM(Bearer token)。
  • 测试时间:2026-09-13。
  • 测试产物:_t3_2026-08.xlsx(950,783 字节 / HTTP 200 / 36.8 秒)、_t3_2026-07.xlsx(942,691 字节 / HTTP 200 / 25.7 秒);归档件 docs/生成汇总大表/输出/生成_道路运输量汇总表_2026-08_四页数据驱动_2026-09-13.xlsx(950,783 字节)。
  • 独立复核脚本:_v5_four.py(输出 _v5_four.txt)、_verify_four.py(输出 _verify_four.txt)。

三、用例表

3.1 正向用例

编号 输入 预期 实际 结论
TC-1 导出 period=2026-08 HTTP 200,正常产出 950,783 字节,36.8 秒 通过
TC-2 与 09-13 13:06 归档件比对 同参数导出结果确定 两次产物同为 950,783 字节 通过
TC-3 后端回填日志 有四页刷新统计、无缺数提示、无异常 「刷新四页(城市汇总/城市分市州/中口径分析/道路运输周转量)数值格数=1056」「刷新排名页数值格数=711」「缺数提示=[]」;最近 4MB 日志无 ERROR/Exception/WARN 通过
TC-4 城市汇总 标题 随报表期改为 1-8 月 / 8 月 A1=2026年1-8月全省累计完成城市客运量情况、A12=2026年8月全省完成城市客运量情况 通过
TC-5 城市汇总 累计块(B3:E9) 客运量/同比/周转量/同比 各 7 行 28 格全部一致(如 B3=269628.07、C3=0.00117、D3=1681467.65、E3=0.00835) 通过
TC-6 城市汇总 当月块(B14:E20) 同上,当月口径 28 格全部一致(如 B14=32215.74、C14=0.0444) 通过
TC-7 城市分市州 标题 ×4 4 块标题随报表期 A1=…1-8月累计情况、A23=…1-8月累计情况、A46=…8月情况、A68=…8月情况 通过
TC-8 城市分市州 4 块 × 17 市州 × 6 值列 6 组值 = 总量/公交/出租/网约车/轨道/轮渡 408 格全部一致 通过
TC-9 中口径分析 标题 + 数值 2 块标题 + 每块 总/班线/城乡公交/城乡出租/城乡网约车 A1=1-8月中口径客运量及周转量、A10=8月中口径客运量及周转量;B3=31528.0607、F3=1227147.4890 等 10 格全部一致 通过
TC-10 道路运输周转量 标题 + 数值 2 块标题 + 17 市州 G/L/Q/W/X/Y A1=2026年1-8月全省累计完成交通周转量情况、A23=2026年8月全省完成交通周转量情况;102 格全部一致(如 G4=17492129.04788293、L4=269628.07、Q4=1227147.48902;W/X/Y 同期列取 2025 年同期累计,如 W4=17492068.4575、X4=269312.48、Y4=1256684.2157) 通过

3.2 负向用例

编号 输入 预期 实际 结论
TC-N1 目标格是母版公式(城市分市州 全省行 B5=G5+L5+Q5+V5+X5、道路运输周转量 J4=G4/W4-1) 不被写值覆盖,保留母版公式 两者仍为公式;四页写入格数 1056 < 四页理论格数,说明公式格被跳过 通过
TC-N2 目标格为空且新值为 0 不新增 0,避免把成品页写成满页 0 SM_货运 无数据的市州轨道/轮渡值未产生新增 0 格 通过
TC-N3 2025 同期无库数据 取母版台账页 2025 列缓存,不出现 NaN/Inf 同比全部为有限数(如 城市汇总 C7=0.4870、C14=0.0444) 通过
TC-N4 台账页读不到市州数据(极端情况) 记 WARN 并**保持母版原值**、不写坏页 代码路径 curCum.isEmpty() → log.warn("…台账页未读到市州数据,跳过(保持母版原值)");本轮台账页数据齐全,未实际触发(**代码审查用例**) 通过(审查)
TC-N5 母版标题为 inlineStr 标题必须真正落盘更新,不能只改 <v> smSetTitle 先 setBlank() 再写,标题校验全部读取到新文案 通过

3.3 回归用例

编号 输入 预期 实际 结论
TC-R1 导出 period=2026-07 不崩,且四页应回退成「1-7 月」口径 HTTP 200 / 942,691 字节 / 25.7 秒;标题 城市汇总 A1=2026年1-7月…、城市客运客运量分市州1-7月累计情况、1-7月中口径客运量及周转量、2026年1-7月全省累计完成交通周转量情况 通过
TC-R2 2026-07 导出值 vs 母版 1-7 月静态权威值 应完全一致(证明口径与母版一致,只是随月份延长) 城市汇总 B3=237412.33000000002(母版 237412.33)、中口径 B3=27524.4906、道路运输周转量 G4=15222118.44638293、城市分市州 B6=135474.77989442425 —— 与母版逐项一致 通过
TC-R3 后端服务可用性 前端首页可访问 http://localhost:8080/ HTTP 200,标题「交通统计报表审核系统」 通过

3.4 逐格独立复核(关键证据)

方法:从生成件**自身的台账页**重新聚合(不读库、不参考任何其它文件),再与四页逐格比对。

复核范围 格数
标题(城市汇总 2 + 城市分市州 4 + 中口径 2 + 道路运输周转量 2) 10
城市汇总 累计块(7 行 × 客运量/同比/周转量/同比) 28
城市汇总 当月块(同上) 28
城市分市州 4 块 × 17 市州 × 6 值列 408
中口径分析 2 块 × 5 行 × 2 列 10
道路运输周转量 2 块 × 17 市州 × 6 列(G/L/Q + J/O/T + W/X/Y) 102
合计 586

结果:**比对 586 格,差异 0 格**(_v5_four.txt 末尾「汇总:比对格数 = 586,差异格数 = 0」)。

补充自洽校验(全省行 = Σ17 市州):道路运输周转量 G4=17492129.04788293 = Σ(G5:G21)、L4=269628.07 = Σ(L5:L21)、Q4=1227147.48902 = Σ(Q5:Q21)、W4/X4/Y4 同理(差 ≤ 6e-11,浮点误差级)。

另:13:06 那一版归档件用 _verify_four.py 复核(含「与母版 1-7 月静态值对照」小节),同样**差异 0 格**。

与母版静态值的对照(证明「确实从静态变动态」):

单元格 母版(1-7 月静态) 生成件(1-8 月)
城市汇总 B3 237412.33 269628.07
城市汇总 A12 2026年7月全省完成城市客运量情况 2026年8月全省完成城市客运量情况
城市分市州 B6 135474.779894424 153695.70483259356
中口径分析 B3 27524.4906 31528.060700000005
道路运输周转量 G4 15222118.4463982 17492129.04788293

四、发现的问题与处置

  1. 母版标题是 inlineStr:POI 直接 setCellValue 只写 <v>、不改 <is>,Excel 仍显示旧文案(7 月)。→ smSetTitle 改为先 setBlank() 再写。
  2. 成品页里混有母版公式(城市分市州全省行、道路运输周转量 J 列同比等):若一律写值会破坏母版自洽公式。→ smSetVal 遇 FORMULA 直接跳过,写入格数 1056 小于四页理论格数即为此。
  3. 城市汇总第 5 行是「出租+网约车」合计,不是单出租。→ 代码按「出租 + 网约车」写入(母版第 6 行才是单出租),与母版口径一致。
  4. 中口径的「城际城乡」不能直接取台账总量。→ 按「总量 − 城市内」计算(仅公交/出租/网约车)。
  5. 库中无 2025 年城市客运/网约车数据。→ 同比基数取母版台账页 2025 年逐月列缓存值(方案 A 的核心),后续 2025 数据入库后可再切换为读库。

五、结论

  • 正向 10 例、负向 5 例、回归 3 例、逐格独立复核 586 格,全部通过。
  • 四张跨页合成页已从**静态**变为**随报表期数据驱动**:导出 2026-08 时标题与数值均为 1-8 月/8 月口径;导出 2026-07 时又能精确回退成与母版一致的 1-7 月权威值。
  • 母版公式保留、同比基数沿用母版 2025 缓存,报表打开后仍走母版自带的重算链路(fullCalcOnLoad)。
  • 遗留:中口径排名页的「同比增速」列仍是母版旧值(库中无 2025 年中口径定稿数据,算不出同比),待 2025 数据入库后刷新。

六、发布与二次独立验证(2026-09-13)

  • 提交 ea7cc07(ReportExportService.java + 本报告 + 《工作日结_2026-09-13》共 3 文件,+689 −2)已推送双仓库:
    git push gitea main(09e612a..ea7cc07)、git push origin main:master(09e612a..ea7cc07),并 git branch -f master main。
  • 推送前 git fetch gitea / git fetch origin 均确认远端无新提交(git rev-list --left-right --count 均为 0 0),未覆盖同事代码。
  • 发布后复跑:重新导出 period=2026-08 → HTTP 200 / 950,783 字节 / 29.2 秒(第三次同尺寸);对发布后产物 _t4_2026-08.xlsx
    再跑一次 586 格独立复核 → 差异 0 格(_v6_four.txt)。
  • 容器级比对:把发布前产物 _t3_2026-08.xlsx 与发布后产物 _t4_2026-08.xlsx 逐 zip 条目比对,**全部内部条目
    (xl/worksheets/*、xl/sharedStrings.xml 等)字节完全一致**;两者 MD5 不同仅源于 xlsx 容器的 zip 头时间戳,功能等价。
  • 运行中的后端(PID 27840)执行的代码即已提交版本(工作区对该 Java 文件 git diff HEAD 为空)。