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

功能测试报告:货运量周转量表多年度工作簿(2021–2026)一次性入库 2026-09-16

功能说明

  • 需求:8 月导入的「定稿-湖北省各市州运输量数据(2026年1-8月).xlsx」一个工作簿内含 21–26 年(源文件缺 2023 年)全部年度数据,要求把这些数据全部读入数据库。
  • 旧行为:importFreightTurnover 只读第 1 个 Sheet,并按「模板_货运量周转量.xlsx」的左右两半(左半今年 1–N 月、右半去年 1–12 月)解析,导致其余年度 Sheet 的数据被直接丢弃。
  • 新行为:导入时先判断是否为「多年度工作簿」(Sheet 数 ≥ 2、每个 Sheet 名形如 2021年、且首行 A 列含「货运量」、B 列含「月」)。
  • 命中:逐 Sheet 解析整年 1–12 月的货运量块与周转量块,**每个年度落一个报表期**(报表期 = 该年最后一个有货运量数据的月份,本次为 YYYY-12),上年同期取上一年度 Sheet。
  • 未命中:完全回退原有月度解析路径,行为与改动前一致。
  • 幂等:仍按报表期「先删后插」;每个年度各写一条 import_batch 记录。

涉及改动

  • 后端 traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java(+153 / −19):
  • importFreightTurnover 改为分流入口;原逻辑整体抽为 importFreightTurnoverByMonth(逻辑与改动前逐行一致)。
  • 新增 detectYearSheets(多年度识别)、importFreightTurnoverByYear(按年解析 + 上年同期)、parseWholeYearSheet(整年 Sheet 解析)、persistFreightTurnover(按报表期先删后插 + 记批次)。
  • 顶部新增 import java.util.TreeMap;。
  • 未改数据库结构、未改前端、未改导入接口签名(仍为 POST /api/import/freightTurnover?period=yyyy-MM)。

测试环境

  • 后端:traffic-audit-server 8090(含本次改动,start-dev.ps1 启动成功,backend.log 出现 Tomcat started on port(s): 8090 / Started TrafficAuditApplication)。
  • 前端:traffic-audit-web 8080(本次不涉及前端)。
  • 数据库:本机 MySQL 127.0.0.1:3308/traffic_audit,用 mysql CLI 直查核对。
  • 源文件:D:\05_数据分类\高速\定稿-湖北省各市州运输量数据(2026年1-8月).xlsx,Sheet 为 ['2026年','2025年','2024年','2022年','2021年'](2026/2025 各 38 行×15 列,2024 48 行×13 列,2022 40 行×15 列,2021 41 行×14 列)。
  • 负向/边界用例一律在一次性测试期 2099-01 ~ 2099-04 内进行,全程不触碰真实月份;测试后已逐个清空。

用例表

# 用例 输入 预期 实际 结论
1 正向-多年度导入 上传源文件,period=2026-08 21/22/24/25/26 五个年度全部入库 返回「共 90 条记录」(5 个报表期 × 18 行);库内新增/覆盖 2021-12、2022-12、2024-12、2025-12、2026-08 通过
2 正向-入库抽查(逐项对齐) 源文件逐年逐市州逐月与库内逐项比对(今年货运量/今年周转量/上年货运量/上年周转量) 完全一致 比对 1080 个单元格,差异 0(脚本 _verify_ft_multi.py) 通过
3 正向-报表期语义 查看各期 report_period 每年度一个报表期 2021-12 / 2022-12 / 2024-12 / 2025-12 / 2026-08;源文件无 2023 年,故未生成 2023-12 通过
4 正向-上年同期 各期 last_* 是否取上一年度 Sheet 有上一年度的有值、无的为空 2022-12、2025-12、2026-08 各 18 行 last_* 全部有值;2021-12(无上年)、2024-12(缺 2023)为空 通过
5 正向-导入批次 查询 import_batch 每个报表期一条记录 首次导入写入 id 324–328(2021-12/2022-12/2024-12/2025-12/2026-08),5 条均 total=success=18、fail=0,file_name 为源文件名 通过
6 负向-单 Sheet 月度模板回退 单 Sheet 月度模板文件 + period=2099-01 识别不命中,回退月度路径 返回「共 18 条记录」,与改动前一致 通过
7 负向-非年度命名多 Sheet 回退 两个非年度命名 Sheet(Sheet1/Sheet2)+ period=2099-02 识别不命中,回退月度路径 code=200,18 条 通过
8 负向-混合命名回退 年度名 + 非年度名混合(2021年/2022年/备注说明)+ period=2099-03 识别不命中,回退月度路径 code=200,18 条 通过
9 负向-非 Excel 文件 文本文件当 xlsx 上传 + period=2099-04 报错且不落库 {"code":500,"message":"导入失败: Can't open workbook - unsupported file type: UNKNOWN"} 通过
10 幂等-重复导入 同一源文件再导一次 不产生重复行、值不变 仍返回「共 90 条记录」;导入后再写 id 332–336;**全表 216 行前后 md5 一致**(a2a733b2c5321a9d5efa9be2e0c5dacb) 通过
11 回归-测试期清理 逐个 POST /api/import/clear?period=2099-0x 测试期数据与批次全部删除 各期 dataRows=18、batchRows=1 删除成功;当前库 0 条 2099 数据、0 条 2099 批次 通过
12 回归-真实月份总量 统计 freight_turnover_import 与导入前口径一致 12 个报表期 × 18 行 = 216 行(2021-12 / 2022-12 / 2024-12 / 2025-12 / 2026-01…2026-08) 通过

发现的问题与处置

  1. 源文件缺 2023 年 Sheet:导致不生成 2023-12 报表期,2024-12 无上年同期(last_* 为空)。属源数据缺口,非代码缺陷;已如实反映在库内。
  2. 报表期语义为「整年」:2021-12 等期实际承载该年 1–12 月的全年数据(而非 12 月单月)。若后续报表/审核按「单月」口径取这些期,需要用户确认口径;本次未做改动。
  3. 重复导入会覆盖同报表期:新逻辑延续「先删后插」的幂等策略,重导 2026-08 会覆盖该期原有值。本次已逐项核对源文件与库内一致(差异 0),无数据损失。
  4. 备份不完整(已记录):改动前的备份 _backup_freight_turnover_before_multiyear_20260916.sql 只有 59642 字节且仅解析出 2026-04 一处 INSERT,不能作为完整回滚依据。**不要把该文件当作完整备份使用。**
  5. 2026-01…2026-07 的 last_* 为空:经核对备份(2026-04)确认这几期在本次改动前 last_* 即为空,且本次导入未触碰这些报表期(批次记录只覆盖 5 个期),故非本次改动引入。

结论

  • 通过。多年度工作簿(21–26 年)已全部入库,逐年一个报表期、逐年上年同期,1080 个单元格逐项比对零差异;非多年度文件自动回退原有月度路径,负向与边界用例均符合预期;重复导入幂等,测试期已清理干净,真实月份数据与改动前口径一致(216 行 / 12 期)。
  • 待用户确认:2021-12 等「整年」报表期的业务口径是否符合后续报表/审核取数要求;如需「逐月报表期」,需要另行改造(本次未做)。