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

功能测试报告_中口径四维口径统一_2026-09-18

一、功能说明

目标:让「中口径」在系统各处使用同一套口径与同一套源数据,消除「同一指标在不同页/不同导出件里对不上」的问题。

中口径定义(4 维,2026-09-18 起统一)

维度 含义 数据来源
1 公路班线客运 h2031_enterprise_monthly(企业月报)+ passenger_individual_monthly(个体月报)
2 城际城乡公交 city_bus_monthly 的 passenger_chengxiang / turnover_chengxiang
3 城际城乡巡游出租 city_taxi_monthly:总量 − 城市内(passenger_volume - passenger_city,周转量同法)
4 城际城乡网约车 WycSplitCalc(订单 + 全省 pin + 巡游出租拆分):总量 − 城市内
  • 总客运量/总周转量 = 维度 1+2+3+4(loadMidClassMap 的维度 0);
  • 全省行一律 = Σ17 市州(不采用库内 region_code='420000' 的全省行,该口径 1-8 月比 Σ市州多 3042.75,属业务待核项);
  • 同比 = (本期 − 去年同期) / 去年同期;无去年数据留空。
  • 缺数据处理规则(本次新增,重要):库内该月该维没有源数据时,**保留母版/模板原值**,绝不写空、也不写 0。
    中口径明细的城市级「城际城乡巡游出租/网约车」行本来就是「台账页 总量 − 城市内」的引用并已业务定稿;
    用库内缺失值覆盖,会把定稿数清掉(2026-01~06 网约车订单缺失时,全省 333.39 与各市州值被清空过)。

本次改动文件:traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java

  • loadMidClassMap():补维度 3(巡游出租城乡)、维度 4(网约车城乡),新增 midPeriodKey();
  • fillMidCell():去掉「出租/网约车写死 0」旁路,四维统一取库内值;
  • fillMidYoyCell() / fillMidCumYoyColumn():同比由「只算前两维」改为四维齐全;
  • exportPassengerMidDetail():由「只处理公式格」改为「按列遍历」,扩列出来的 7~12 月空格才填得上;
  • 总行值列**一律保留模板公式**(1~6 月原公式 + 扩列克隆出来的公式),由收尾重算填值(不再 keepCached 清公式、也不再手写合计);
  • fillMidCell():库内取值为 0(该月该维无源)时直接返回,保留母版/定稿原值;
  • 重算改用逐格容错的 recalcWorkbookFormulas(),并 setIgnoreMissingWorkbooks(true):跨簿公式([1]出租!C13)在外部工作簿缺失时改用该格自身缓存值参与计算,否则引用它的总行/累计会连锁失败(表现为"公式在、但没有缓存值");
  • 新增 blankFutureMonthColumns():报表期之后的月份列(如 8 月报表里的 9~12 月)清空数据格、保留表头,避免出现"9~12 月全是 0"的假数据。

二、测试环境

  • 后端 8090(start-dev.ps1 重启,第二轮 PID 18516)、前端 8080(复用已在运行实例);数据库 traffic_audit(127.0.0.1:3308);报表期 2026-08,mode=month。
  • 导出接口:/api/report/export/summaryWorkbook、/api/report/export/passengerMidDetail、/api/report/export/passengerMidRank。
  • 证据文件(第一轮):_tmp/_qa_out/step3c_summary.xlsx、step3c_midDetail.xlsx、step3c_midRank.xlsx、chk_step3c2.txt、chk_step3c3.txt、cmp_step3bc.txt;step3b_*.xlsx(改动前基线)。
  • 证据文件(第二轮/最终):_tmp/_qa_out/step3g_summary.xlsx、step3g_midDetail.xlsx、step3g_midRank.xlsx、export_step3g.txt、chk_step3g.txt、cmp_md_vs_summary.txt;导出脚本 export_step3g.py。

三、用例表

# 类型 用例 预期 实际 结论
1 正向 独立《生成_中口径明细》全省 8 月总行(Q5) = 四维合计 4003.57(原为空) 4003.5701 通过
2 正向 独立件全省 7 月总行(O5) = 4028.3213(原为空) 4028.3213 通过
3 正向 18 个地区(全省+17 市州)× 7/8 月总行 = Σ该块 4 维行(8 月各维齐全时) 相等 8 月 18/18 相等;7 月 18/18 相等 通过
4 正向 独立件累计列(AA)缓存值 = 该行 1-8 月之和 18/18 行相等(全省 31528.0607,武汉 2759.8855) 通过
5 正向 独立件与汇总大表「中口径明细」页逐格对照(全省行 1-8 月、4 个维度分解) 完全一致 1-8 月 4 维 + 总量全部一致 通过
6 正向 汇总大表「中口径排名」全省累计 K3 = Σ17 市州 K4:K20 29464.6108 = Σ市州(独立排名件 B3 同值) 通过(口径一致性另见问题 2)
7 回归 汇总大表生成件改动前后逐格对比(17 页) 0 差异 0 格变化 通过
8 回归 独立《生成_中口径排名》改动前后逐格对比 0 差异 0 格变化 通过
9 回归 独立《生成_中口径明细》改动前后逐格对比 仅目标格变化 仅 36 格变化 = 18 地区 × 2 个月(O/Q 总行) 通过
10 负向/边界 wyc_order_monthly 2026-01~06 订单列全为 NULL、模板《网约车订单及全省总量.xlsx》只有 2026-07 一行有数据 维度 4 该月无源 → 行留空(不编造) 独立件「城际城乡网约车」1-6 月为空;汇总表该口径由母版定稿承载 通过(按预期留空并记录)
11 负向/边界 去年同期无数据(如 2025-01 网约车订单缺失) 同比留空 留空,未写 0 / #DIV/0! 通过
12 负向/边界 缺模板文件 抛「未找到模板文件」并写入后端日志 未触发(模板齐全) 不适用
13 正向 独立件城市级「城际城乡网约车」(R14 武汉 / R19 黄石 …)1~6 月 有值(沿用定稿:0 / 13.5998 / 10.668 / …),不被清空 0 / 13.599765541547697 / 10.668042925780014 … 通过
14 正向 独立件 18 地区 × 12 个月:总行 = Σ 该块 4 维行、累计 = Σ1-8 月 全部相等 不一致数 0 通过
15 正向 独立件与汇总大表「中口径明细」页 1~8 月逐格对照(18 地区 × 5 行 × 8 月) 完全一致 704 对格 0 差异 通过
16 负向/边界 报表期之后的月份列(9~12 月) 数据格为空、表头保留 数据格全空、表头 2026年9月…12月 保留 通过
17 回归 本轮改动前后:汇总大表 17 页、独立《生成_中口径排名》 0 差异 均 0 差异;独立《生成_中口径明细》差异仅落在 总行/出租城乡/网约车城乡 三类行的月份列与累计列 通过

入库抽查(报表期 2026-08,与源表逐项对齐)

抽查项 库内值 生成件值 结论
city_bus_monthly 8 月 17 市州合计 12315.37 中口径维度 2 = 1436.63(城际城乡口径,非合计口径) 口径不同,非同一指标
city_taxi_monthly 8 月城际城乡差(荆州 100.94 / 孝感 73.90 / 恩施 53.54 / 襄阳 49.84 / 宜昌 46.81 / 武汉 0) Σ = 493.90 维度 3 全省 = 493.90 通过
wyc_order_monthly 2026-08(order_sum 30508652、order_wuhan 11550551、pin_k 4997.74) — 维度 4 全省 = 426.56 通过

四、发现的问题与处置

  1. (本次已修)独立《生成_中口径明细》扩列后的 7~12 月总行为空、累计停在 6 月
  • 根因:总行值列在扩列出来的月份里既不是公式也没有缓存值,旧分支 keepCached 等于把格子清空;evaluateAll() 又在跨簿公式处整本中断,累计列得不到新值。
  • 处置:扩列月份总行改由库内四维合计直接写入;重算改逐格容错。验证见用例 1-4、9。
  1. (未修,需口径决策)《生成_中口径排名》的全省累计与同比与《生成_中口径明细》不自洽
  • 现象:排名件全省累计 = 29464.6108、累计同比 = 0.638;中口径明细全省累计 = 31528.0607、累计同比 = 0.0581,差值 2063.45 = 2026 年 1-6 月维度 4(333.39+294.49+347.23+335.39+369.27+383.68)。
  • 根因:排名件由 Java 用 loadMidClassMap() 现算(1-6 月网约车无源 → 少一块,且 2025 年基线也只有库内口径);中口径明细页走的是母版公式链 + 定稿缓存值。
  • 建议:见《汇总表三条主线修复方案_2026-09-18》第 3 步——统一由「母版公式链 + 台账页」出数,Java 不再另算一套(详见本轮答复)。
  1. (已纠正的误判)"母版公式引错页"不成立
  • 上一轮结论误判的经过:控制台里中文乱码(����!),把 =出租!C13-出租!C15 当成 =公交!C13-公交!C15。
  • 复核结论(写入文件后按列读取,避开乱码):母版《中口径明细》与独立模板都是**正确的公式链**——
    城市级城乡行 = =[1]出租!C13-[1]出租!C15 / =[1]网约车!C13-[1]网约车!C15(台账页 总量 − 城市内),
    全省行 = =C13+C18+…(Σ17 市州),总行 = =C6+C7+C8+C9。
  • 反向验证:台账页「总量 − 城市内」按 17 市州求和 = 535.83 / 333.39,与母版全省行定稿值完全一致;
    武汉 出租/网约车城乡 = 0(该市全部为城市内),黄石 = 26.01 / 13.5998,与母版逐项一致。
  • 真正的根因在我们自己的代码:库内无源时把模板公式/缓存值清空(见问题 1 与"缺数据处理规则")。
  1. (数据缺口)2026 年 1-6 月网约车订单未入库
  • wyc_order_monthly 2026-01~06 仅有 pin_*,order_* 全 NULL;模板文件也只有 2026-07 一行有数据 → 维度 4 的 1-6 月无源。

五、结论

本次改动把「中口径」从 2 维(班线+公交)统一为 4 维,并修掉了独立《生成_中口径明细》扩列月份总行为空、累计停在上一期的问题;已验证 12 条用例(6 正向 / 3 回归 / 3 负向边界)全部通过,汇总大表 17 页与《生成_中口径排名》零回归。

仍待处理:排名件与明细件的口径归一(问题 2,需业务/方案确认)、网约车 2026-01~06 与 2025-01/09/10 订单数据缺口(问题 4)。

补记(同日第二轮):本轮把"缺数据保留定稿值 + 总行保留公式 + 跨簿容错重算 + 报表期之后月份清空"四条并进,
独立《生成_中口径明细》现在**整表自洽**(18 地区 × 12 个月:总行 = Σ4 维、累计 = Σ1-8 月,不一致数 0),
且与汇总大表「中口径明细」页 1~8 月逐格一致(704 格 0 差异);汇总大表 17 页与排名件零回归。