zhizhijie
2026-09-19 ade4387f72c876f779b0956295922003464434f0
fix(汇总表): 中口径排名周转量口径统一为「总量-城市内」差额法

问题:同一本汇总大表里,「中口径排名」页公交城际城乡走逐企业行「字段值>0取字段值、否则总量-城市内」,与台账页/中口径明细/四页合成页的差额法不一致;源报表三个数各自两位小数舍入,2026年1-8月全省72行「城际城乡 != 总量-城市内」(差±0.01),累加后排名页比人工核对列多 0.31978 万人公里(孝感+0.08、宜昌/荆州+0.05、武汉/黄冈/天门+0.04…)。

修复:loadMidClassMap 公交维度一律用「总量 - 城市内」现算。

验证:重启后端重新生成 2026-08 汇总表,17 市州排名周转量与明细/人工逐格归零;客运量、同比、中口径分析页、四页合成页无回归;2025 同比基期 0 行受影响。全省行仍差 0.0002 万人公里(母版 =SUM(O4:O20) 先四舍五入后求和的固有结构)。详见功能测试报告 2026-09-19。
2个文件已修改
1个文件已添加
102 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_中口径排名周转量口径统一_2026-09-19.md 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-19.md 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Öпھ¶ÅÅÃûÖÜתÁ¿¿Ú¾¶Í³Ò»_2026-09-19.md
New file
@@ -0,0 +1,67 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_中口径排名周转量口径统一_2026-09-19
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
**问题来源**:用户核对桌面《生成_道路运输量汇总表 (1).xlsx》时,在「中口径排名」页手工加了一列
「人工-周转量」(逐月各分项相加),发现与程序生成的「周转量」列有差异(全省 +0.31978 ä¸‡äººå…¬é‡Œï¼Œ
各市州 Â±0.01~0.08),要求定位原因并修复。
**根因**:同一本汇总大表里两页走了两套取数口径。
- ã€Œä¸­å£å¾„排名」页周转量来自后端 `ReportExportService.loadMidClassMap()` å…¬äº¤ç»´åº¦ï¼š
  **逐企业行**判断——该行「城际城乡周转量」> 0 å°±å–字段值,= 0 æ‰å›žé€€ã€Œæ€»é‡ âˆ’ åŸŽå¸‚内」。
- ã€Œä¸­å£å¾„明细」「道路运输周转量」「中口径分析」等页走台账口径
  ï¼ˆ`smReadLedgerMetrics()`):先按市州按月汇总,再 åˆè®¡æ€»é‡ âˆ’ åˆè®¡åŸŽå¸‚内。
源报表里「总量/城市内/城际城乡」三个数各自保留两位小数,个别企业行上
`城际城乡 â‰  æ€»é‡ âˆ’ åŸŽå¸‚内`(差 Â±0.01)。2026 å¹´ 1-8 æœˆè¿™ç±»è¡Œå…± **72 è¡Œ**,
程序采信字段值、人工用差额法,累加后即出现该差异。
**修改内容**:`traffic-audit-server/.../reportexport/service/ReportExportService.java`
(公交维度,原 2458/2460 è¡Œé™„近)——城际城乡一律用「总量 âˆ’ åŸŽå¸‚内」现算,与台账页/明细页/四页合成口径一致。
## äºŒã€æµ‹è¯•环境
| é¡¹ | å†…容 |
| --- | --- |
| åŽç«¯ | Spring Boot,`localhost:8090`,改后重新编译并重启(`start-dev.ps1`) |
| æ•°æ®åº“ | MySQL `localhost:3308/traffic_audit`(`city_bus_monthly` ç­‰ï¼‰ |
| æŠ¥è¡¨æœŸ | 2026-08(1-8 æœˆç´¯è®¡ + 8 æœˆå•月块) |
| å¯¹ç…§ä»¶ | `D:\桌面\生成_道路运输量汇总表 (1).xlsx`(改前生成 + ç”¨æˆ·äººå·¥åˆ—) |
| ç”Ÿæˆä»¶ | æŽ¥å£ `/api/report/export/summaryWorkbook?period=2026-08` â†’ `_after_busfix_2026-08.xlsx` |
| è¾…助脚本 | `_qa_busfix.py`、`_qa_busfix2.py`、`_qa_busfix3.py`、`_qa_busfix_diff.py`、`_qa_busfix_err.py`、`_qa_busfix_hist.py` |
## ä¸‰ã€ç”¨ä¾‹ä¸Žç»“æžœ
| ç¼–号 | ç±»åž‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T1 | æ­£å‘ | æ”¹åŽç”Ÿæˆä»¶ã€Œä¸­å£å¾„排名」O åˆ— vs ã€Œä¸­å£å¾„明细」S åˆ—,17 å¸‚å·ž | é€æ ¼ç›¸ç­‰ | 17/17 å…¨éƒ¨ç›¸ç­‰ï¼ˆæ­¦æ±‰ 152330.8912、孝感 64429.9445、随州 59015.4820…) | é€šè¿‡ |
| T2 | æ­£å‘ | å…¨çœç´¯è®¡å‘¨è½¬é‡ï¼ˆæŽ’名页 O3) | = æ˜Žç»†/人工 1227147.48902 | 1227147.4888(差 âˆ’0.0002 ä¸‡äººå…¬é‡Œ = 2 äººå…¬é‡Œï¼‰ | é€šè¿‡ï¼ˆå·®å¼‚见「五、遗留」) |
| T3 | æ­£å‘ | æ­¦æ±‰ç´¯è®¡å‘¨è½¬é‡ | = äººå·¥åˆ— 152330.8912 | 152330.8912 | é€šè¿‡ |
| T4 | æ­£å‘ | 8 æœˆå•月块 17 å¸‚州合计 | = æ˜Žç»† 8 æœˆåˆè®¡ | å‡ä¸º 156017.6956 | é€šè¿‡ |
| T5 | æ­£å‘ | ç‹¬ç«‹æŽ¥å£ `passengerMidAnalysis`(城际城乡公交累计周转量) | = å°è´¦å£å¾„ 227126.74 | 227126.74(改前 227127.06) | é€šè¿‡ |
| T6 | æ­£å‘ | ç‹¬ç«‹æŽ¥å£ `passengerMidRank` å…¨çœç´¯è®¡å‘¨è½¬é‡ | æŽ¥è¿‘ 1227147.489 | 1227147.4888 | é€šè¿‡ |
| T7 | å›žå½’ | æ”¹å‰/改后「中口径排名」客运量列(17 å¸‚å·ž + å…¨çœï¼‰ | ä¸å˜ | å®Œå…¨ä¸€è‡´ | é€šè¿‡ |
| T8 | å›žå½’ | ã€Œä¸­å£å¾„分析」页 ç´¯è®¡å‘¨è½¬é‡ï¼ˆå°è´¦å£å¾„) | ä¸å˜ | é€æ ¼ä¸€è‡´ï¼ˆ1227147.48902 / 904146.38902 / 227126.74…) | é€šè¿‡ |
| T9 | å›žå½’ | åŒæ¯”列(全省 âˆ’2.35%、武汉 +4.15% ç­‰ï¼‰ | ä¸å˜ | æ˜¾ç¤ºç²¾åº¦å†…完全一致 | é€šè¿‡ |
| T10 | å›žå½’ | æ•´æœ¬å·¥ä½œç°¿é€æ ¼å¯¹æ¯”改前/改后 | ä»…目标格变化 | é™¤ç›®æ ‡åˆ—外只出现 1e-10 çº§æµ®ç‚¹å™ªå£° | é€šè¿‡ |
| T11 | è¾¹ç•Œ | 2025 å¹´åŸºæœŸï¼ˆåŒæ¯”基数) | ä¸å—影响 | `city_bus_monthly` 2025 å¹´ã€Œå­˜å‚¨åŸŽé™…城乡 â‰  æ€»é‡âˆ’城市内」行数 = 0 | é€šè¿‡ |
| T12 | è¾¹ç•Œ | åŽŸã€Œå­˜å‚¨å€¼ç¼ºå¤±ï¼ˆ<=0)才回退」兜底是否仍需要 | åŽ»æŽ‰åŽæ— å‰¯ä½œç”¨ | 2025/2026 å‡æ— ã€Œæœªå­˜åŸŽé™…但 æ€»é‡âˆ’内>0」的行(0 è¡Œï¼‰ï¼Œå…œåº•从未触发 | é€šè¿‡ |
| T13 | è´Ÿå‘ | æºåº“ 72 è¡Œã€Œå­˜å‚¨åŸŽé™…城乡 â‰  æ€»é‡âˆ’城市内」 | ç»Ÿä¸€æŒ‰å·®é¢æ³• | 17 å¸‚州差值全部归零(改前:武汉 +0.04、孝感 +0.08、随州 âˆ’0.02…,全省 +0.3198) | é€šè¿‡ |
| T14 | è´Ÿå‘ | ã€Œç­çº¿åŒ…车」页 2020 å¹´åŽ†å²åˆ— `#VALUE!` | éžæœ¬æ¬¡å¼•å…¥ | æ”¹å‰åŽ†å²ç”Ÿæˆä»¶åŒä¸º 236/456 æ ¼ï¼›Excel æ‰“开会按 `fullCalcOnLoad` é‡ç®— | é€šè¿‡ï¼ˆæ—¢æœ‰çŽ°è±¡ï¼‰ |
## å››ã€å‘现的问题与处置
1. **口径不一致(本次根因)**:公交维度逐企业行采信「城际城乡」字段,与台账页差额法冲突 â†’ å·²ç»Ÿä¸€ä¸ºå·®é¢æ³•。
2. **全省行残留 0.0002 ä¸‡äººå…¬é‡Œ**:排名页全省行是母版公式 `=SUM(O4:O20)`,各市州先四舍五入到 4 ä½å†æ±‚和,
   ä¸Žã€Œæ˜Žç»†å…¨ç²¾åº¦æ±‚和」天然差 2 äººå…¬é‡Œï¼Œå±žæ¯ç‰ˆå…¬å¼ç»“构性问题,本次未动母版。
3. **历史列 `#VALUE!`**:POI é‡ç®— 2020 å¹´åŒæ¯”列的既有现象,与本次改动无关,Excel æ‰“开即自动重算。
## äº”、结论
- ä¿®å¤åŽã€Œä¸­å£å¾„排名」周转量与人工/台账口径 **17 ä¸ªå¸‚州逐格一致**,差异从 17 é¡¹å½’é›¶ï¼›
- å®¢è¿é‡ã€åŒæ¯”、分析页、四页合成页均无回归;
- 2025 åŒæ¯”基期不受影响;
- æ®‹ç•™ 0.0002 ä¸‡äººå…¬é‡Œï¼ˆ2 äººå…¬é‡Œï¼‰æ¥è‡ªæ¯ç‰ˆå…¨çœè¡Œ SUM å…¬å¼ï¼Œå»ºè®®åŽç»­å•独拍板是否改为全精度写值。
测试人:Codex(AI) 测试日期:2026-09-19
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-19.md
@@ -82,6 +82,22 @@
- è¿½åŠ ï¼šç¡®è®¤ã€Œ4 ä½å°æ•°ã€çš„适用范围(货运量/周转量 4 ä½å³å…¨ç²¾åº¦ï¼Œ754 ä¸ªå¯¹è±¡ 0 ä¾‹å¤–ï¼›
  è¿è·ã€åŒæ¯”不等于全精度),据此把汇总类查询(1/3/5/8)的 14 å¤„小数位统一为 4 ä½ã€‚
  æ”¹åŽè„šæœ¬è¾“å‡ºä¸Ž 545 å®¶äº¤ä»˜ä»¶å¸‚州汇总逐列对齐(T27~T30,累计 30 æ¡ç”¨ä¾‹ï¼‰ã€‚
### 4. æ±‡æ€»å¤§è¡¨ã€Œä¸­å£å¾„排名」周转量口径统一(用户桌面核出差异 â†’ å®šä½ â†’ ä¿®å¤ï¼‰
用户把人工算的一列(「人工-周转量」)放进桌面《生成_道路运输量汇总表 (1).xlsx》的「中口径排名」页,
问为什么和程序生成的「周转量」对不上(全省 +0.31978 ä¸‡äººå…¬é‡Œï¼Œå„市州 Â±0.01~0.08)。
- **定位**:同一本表里两页口径不同。「中口径排名」走 `loadMidClassMap()` å…¬äº¤ç»´åº¦â€”—**逐企业行**
  ã€ŒåŸŽé™…城乡字段 > 0 å°±ç”¨å­—段值,= 0 æ‰å›žé€€ æ€»é‡ âˆ’ åŸŽå¸‚内」;「中口径明细/分析/道路运输周转量」走台账口径
  `smReadLedgerMetrics()`——先按月按市州汇总再 æ€»é‡åˆè®¡ âˆ’ åŸŽå¸‚内合计。
  æºæŠ¥è¡¨ä¸‰ä¸ªæ•°å„自两位小数舍入,2026 å¹´ 1-8 æœˆå…¨çœæœ‰ **72 è¡Œ**企业月报
  `城际城乡 â‰  æ€»é‡ âˆ’ åŸŽå¸‚内`(差 Â±0.01),程序采信字段值、人工用差额法,累加即成差异。
  æŒ‰ä¼ä¸šè¡Œé‡ç®—的运输口径差**逐市州与表里差列完全吻合**(孝感 +0.08、宜昌/荆州 +0.05、武汉/黄冈/天门 +0.04…)。
- **修复**:`ReportExportService.java` å…¬äº¤ç»´åº¦æ”¹ä¸ºä¸€å¾‹ã€Œæ€»é‡ âˆ’ åŸŽå¸‚内」现算(与台账页/明细页/四页合成口径一致)。
- **验证**:重启后端重新生成 2026-08 å¤§è¡¨ï¼Œã€Œä¸­å£å¾„排名」周转量与人工/明细口径 **17 å¸‚州逐格归零**;
  å®¢è¿é‡ã€åŒæ¯”、分析页、四页合成页无回归;2025 åŒæ¯”基期 0 è¡Œå—影响(改后 17 å¸‚州差全 0)。
- å–证脚本与生成件:`_qa_busfix*.py`、`_after_busfix_2026-08.xlsx`、`_after_midrank.xlsx`、`_after_midana.xlsx`。
## äºŒã€æµ‹è¯•结果摘要
见《功能测试报告_持续在规企业545家分市州累计运距同比_2026-09-19.md》:11 æ¡ç”¨ä¾‹ï¼ˆ7 æ­£å‘ / 3 è¾¹ç•Œ / 1 è´Ÿå‘)全部通过。
@@ -92,12 +108,20 @@
- åŒåä¼ä¸šå£å¾„ SQL è„šæœ¬å·²æ•´è„šæœ¬æ‰§è¡ŒéªŒè¯ï¼ˆå«è¿½åŠ çš„æ˜Žç»†å¯¼å‡ºæŸ¥è¯¢ï¼‰ï¼š17 æ¡ç”¨ä¾‹ï¼ˆ11 æ­£å‘ / 2 è´Ÿå‘ / 4 è¾¹ç•Œï¼‰å…¨éƒ¨é€šè¿‡ï¼›
  æ˜Žç»† 545 è¡Œæ±‚å’Œ = æ±‡æ€»è¡Œï¼ˆå·®å¼‚ 0),差异企业闭合校验通过。
- ä¸­å£å¾„排名周转量口径统一:14 æ¡ç”¨ä¾‹ï¼ˆ6 æ­£å‘ / 1 å›žå½’组 / 3 è¾¹ç•Œ / 3 è´Ÿå‘回归)全部通过,
  è¯¦è§ã€ŠåŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_中口径排名周转量口径统一_2026-09-19.md》;
  å…¨çœè¡Œä»æ®‹ç•™ 0.0002 ä¸‡äººå…¬é‡Œï¼ˆ=2 äººå…¬é‡Œï¼Œæ¯ç‰ˆ `=SUM(O4:O20)` å…ˆå››èˆäº”入后求和的固有结构)。
## ä¸‰ã€é—留问题与待办
1. ç”¨æˆ·è¡¨æ ¼ O åˆ—高速运距同比的来源/期间待确认(需与 N åŒä¸º 1-8 æœˆç´¯è®¡ï¼‰ï¼Œç¡®è®¤åŽæ–¹å¯ç®—「运距增速差」。
2. 09-18 äº¤ä»˜çš„《货运月报_持续在规企业_分市州1-8月累计运距及同比》采用**官方全口径**(同比 +4.54%);
   æœ¬è¡¨é‡‡ç”¨**两年持续在规 545 å®¶å£å¾„**(同比 +2.90%),两版口径不同但都已注明,供业务按场景选用。
3. è‹¥è¯¥è¡¨è¦éšã€Šå·®å¼‚率汇总表》上报,建议加注两种口径的差异原因(规上企业名单变动)。
4. ã€Œä¸­å£å¾„排名」全省行(母版公式 `=SUM(O4:O20)`)与明细全精度求和差 0.0002 ä¸‡äººå…¬é‡Œï¼Œ
   æ˜¯å¦æ”¹æˆå…¨ç²¾åº¦å†™å€¼ï¼Œå¾…用户拍板。
5. æºæŠ¥è¡¨ `city_bus_monthly` ä¸­ 72 è¡Œã€ŒåŸŽé™…城乡 â‰  æ€»é‡ âˆ’ åŸŽå¸‚内」的两位小数舍入差异,
   å·²æŒ‰å·®é¢æ³•统一;如后续要与上报口径完全对齐,需回头与填报方确认该字段口径。
## å››ã€æ˜Žå¤©è®¡åˆ’
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -2454,11 +2454,12 @@
            String city = RegionUtil.normalizeCityName(b.getCity());
            if (city == null) continue;
            int key = y * 100 + m;
            // B1 å…œåº•:存储的「城际城乡」缺失(<=0)时用「总客运量 âˆ’ åŸŽå¸‚内」现算,避免 2025 å…¨å¹´å…¬äº¤ç»´åº¦è¢«å½“成 0
            double cxPass = nz(b.getPassengerChengxiang());
            if (cxPass <= 0) cxPass = nz(b.getPassengerVolume()) - nz(b.getPassengerCity());
            double cxTurn = nz(b.getTurnoverChengxiang());
            if (cxTurn <= 0) cxTurn = nz(b.getTurnover()) - nz(b.getTurnoverCity());
            // å£å¾„统一(2026-09-19,用户核对「中口径排名」周转量 vs äººå·¥åˆ—):城际城乡一律用「总量 âˆ’ åŸŽå¸‚内」现算。
            // åŽŸé€»è¾‘ã€Œå­˜å‚¨çš„åŸŽé™…åŸŽä¹¡ > 0 å°±ä¼˜å…ˆå–字段值,<=0 æ‰å›žé€€åˆ°å·®é¢æ³•」会在个别企业行上与差额法差 Â±0.01
            // ï¼ˆæºæŠ¥è¡¨é‡Œæ€»é‡/城市内/城际城乡各自两位小数舍入,2026 å¹´ 1-8 æœˆå…¨çœå…± 72 è¡Œï¼‰ï¼Œç´¯åŠ åŽ
            // ã€Œä¸­å£å¾„排名」页比「中口径明细」/人工口径多 0.32 ä¸‡äººå…¬é‡Œã€‚改为差额法后与台账页、明细页、四页合成口径一致。
            double cxPass = nz(b.getPassengerVolume()) - nz(b.getPassengerCity());
            double cxTurn = nz(b.getTurnover()) - nz(b.getTurnoverCity());
            if (cxPass < 0) cxPass = 0.0;
            if (cxTurn < 0) cxTurn = 0.0;
            addMidClass(mid, key, city, 2, cxPass, cxTurn);