feat(投资): 投资系统导出新模板按表头解析 + 审核基准缺失保护 + 十堰源文件清理

- importInvestmentSystem 改为按表头关键字定位列(findColByKeywords),兼容新模板《2026年X月投资系统项目明细》(多项目所处阶段/少自年初累计)与老模板《模板_查询结果》

- 缺「自年初累计」列时 year_cum 留空(不错填);checkInvestCrossDiff 增加「基准缺失即跳过 + WARN 日志」,避免把 NULL 当 0 导致成片误报(RULE_I002 实测 0 条)

- 十堰物流汇总表源文件删除武汉段27+黄石段4(Excel COM 整行删除),原件备份到 docs/投资/输出/源文件备份/;重导验证该文件 38->7 条,库内仍 152 项目/136 条 2026-08 月度数

- 数据: 新模板 2026-08 导入 129 条(investment_system 2026-07=148 不受影响)

- 文档: 功能测试报告(11 用例) + 日结 1.5 + 交接文档 P0-1 闭环与新 P1-13
1个文件已删除
5个文件已修改
2个文件已添加
175 ■■■■■ 已修改文件
docs/交接文档_2026-09-21.md 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_投资系统新模板按表头解析与审核基准缺失保护_2026-09-21.md 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-21.md 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/模板_查询结果(投资系统-客运+物流 2026.7).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/湖北省十堰交通物流基础设施投资统计汇总表(月报)(2026年8月).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输出/源文件备份/湖北省十堰交通物流基础设施投资统计汇总表(月报)(2026年8月)_原始含武汉黄石_20260921.xls 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/½»½ÓÎĵµ_2026-09-21.md
@@ -11,8 +11,10 @@
## 0. å…ˆè¯»è¿™ä¸€é¡µï¼ˆæŽ¥æ‰‹çš„第 1 å°æ—¶ï¼‰
1. **先把系统跑起来**,再谈改代码。见 Â§7.1(一键脚本,必须在沙箱外执行)。
2. **当前最紧急的 4 ä»¶äº‹**(详见 Â§4 P0):① 8 æœˆåå °ç‰©æµæºæ–‡ä»¶é‡Œçš„「非十堰段」会反复把 31 ä¸ªé¡¹ç›®å¸¦å›žåº“;② ã€Šäº¿å…ƒæŠ•资项目》月份列每月覆盖上月;
   â‘¢ å¯¼å‡ºå‰ã€ŒåŸºæ•°ä½“检 + å¼¹çª— +《数据缺失清单》页」只做了一半;④ ç¼º 2026-06 / 2026-09 æ¯ç‰ˆï¼Œé‚£ä¸¤æœŸå‡ºä¸äº†è¡¨ã€‚
2. **当前最紧急的 4 ä»¶äº‹**(详见 Â§4 P0):① ã€Šäº¿å…ƒæŠ•资项目》月份列每月覆盖上月(用户 Q7 è¦çš„「加一列」未做);
   â‘¡ å¯¼å‡ºå‰ã€ŒåŸºæ•°ä½“检 + å¼¹çª— +《数据缺失清单》页」只做了一半;③ ç¼º 2026-06 / 2026-09 æ¯ç‰ˆï¼Œé‚£ä¸¤æœŸå‡ºä¸äº†è¡¨ï¼›
   â‘£ æ±‡æ€»å¤§è¡¨ã€Œä¸­å£å¾„排名 vs ä¸­å£å¾„明细」历史同比基数双轨制(16 ä¸ªå¸‚州有差)。
   > åŽŸã€Œ8 æœˆåå °ç‰©æµæºæ–‡ä»¶å«éžåå °æ®µã€å·²äºŽ 2026-09-21 é—­çŽ¯ï¼Œè§ Â§4 P0-1。
3. **别自己拍板业务口径**,第 5 ç« åˆ—的是必须业务确认的事。
4. æ”¹å®Œå¿…须:写《功能测试报告》→ æ›´æ–°ã€Šå·¥ä½œæ—¥ç»“》→ åŒä»“库推送(§7.4)。这是本项目的硬规矩。
@@ -41,6 +43,7 @@
| `freight_turnover_import` | **234** | 18 è¡Œ/期 Ã— 13 æœŸï¼ˆ2021-12 ~ 2026-08) |
| `h2031_enterprise_monthly` | 15811 | å…¬è·¯æ—…客(中口径维度 1 çš„æ¥æºä¹‹ä¸€ï¼‰ |
| `h2032_enterprise_monthly` | 13056 | è´§è¿ä¼ä¸šæœˆæŠ¥ |
| `investment_system` | 2026-07: 148 / **2026-08: 129** | æŠ•资系统导出(投资审核的比对基准);08 æœŸç”¨**新模板**导入 |
| `import_batch` | 417 | å¯¼å…¥æ‰¹æ¬¡å°è´¦ï¼ˆå¼‚步导出的「数据版本守卫」用它) |
- **2026-09 è„æœŸå·²æ¸…理干净**(本次核实:`h204_vehicle_quarterly` åªæœ‰ 2026-07/08;`audit_run`/`audit_result` åªæœ‰ 2026-05~08;`investment_monthly` åªæœ‰ 06~08)。
@@ -55,7 +58,7 @@
| HEAD | `a08c70d feat(投资): å¸‚州月报统一填报模板 + åŽ¿(市、区)列解析 + è¡¨å¤´è¡Œåˆ¤å®šæ”¶ç´§` |
| ä¸ªäººè¿œç«¯ | `origin` â†’ `https://gitee.com/zhizhijie/traffic-audit.git`(分支 `master`) |
| å…¬å¸è¿œç«¯ | `gitea` â†’ `http://61.183.254.94:3000/r/trafficAudit.git`(分支 `main`,账号 zyj) |
| æœªæäº¤æ–‡ä»¶ | æœ¬äº¤æŽ¥å½“时的未跟踪文件:`docs/问题汇总/汇总大表问题交接_2026-09-21.md`、`docs/工作日结/工作日结_2026-09-21.md`、`docs/投资/输入/2026å¹´8月投资系统项目明细.xls`、`docs/交接文档_2026-09-21.md`(随本次交接一并提交) |
| å·¥ä½œåŒºçŠ¶æ€ | å¹²å‡€ï¼ˆäº¤æŽ¥æ–‡æ¡£ã€æ±‡æ€»å¤§è¡¨é—®é¢˜äº¤æŽ¥ã€æ—¥ç»“、投资系统新模板支持均已提交并推送两端) |
### 1.4 å…³é”®ç›®å½•
@@ -182,7 +185,7 @@
| # | äº‹é¡¹ | çŽ°è±¡ / å½±å“ | çŽ°çŠ¶ä¸Žè¯æ® | ä¸‹ä¸€æ­¥ | çŠ¶æ€ |
| --- | --- | --- | --- | --- | --- |
| P0-1 | **8 æœˆåå °ç‰©æµæ±‡æ€»è¡¨å«ã€Œéžåå °æ®µã€** | è¯¥æ–‡ä»¶ä¸€ä¸ªé¡µç­¾æ”¶äº†å…¨çœï¼š8 æœˆè¿™ä»½ 38 è¡Œé‡Œåªæœ‰ **7 è¡Œæ˜¯åå °**,另 **27 è¡Œæ­¦æ±‰ + 4 è¡Œé»„石**。程序特意支持「按小节行切市州」,所以每次重导 8 æœˆç‰©æµéƒ½ä¼šæŠŠè¿™ 31 ä¸ªé¡¹ç›®å»ºåˆ°æ­¦æ±‰/黄石名下(09-20 å·²å®žæµ‹å¤çް +31 é¡¹ç›®ï¼Œç”Ÿæˆè¡¨æ­¦æ±‰ç‰©æµæ®µä¼šå¤š 27 è¡Œï¼‰ | åº“已清干净(152 é¡¹ç›® / 284 æœˆåº¦æ•°ï¼Œ2026-08 æœˆåº¦æ•° 136 è¡Œä¸Žé‡å¯¼å‰é€å€¼ä¸€è‡´ï¼‰ï¼›**源文件未清** | ç”¨æˆ·ç¡®è®¤åŽç”±æŽ¥æ‰‹äººåˆ æ®µï¼ˆå…ˆå¤‡ä»½åˆ° `docs/投资/输出/`),或用户自行在 Excel åˆ é™¤è¯¥ä¸¤æ®µ | âŒ |
| P0-1 | ~~8 æœˆåå °ç‰©æµæ±‡æ€»è¡¨å«ã€Œéžåå °æ®µã€~~ | â€”— | **已闭环(2026-09-21)**:用户确认「清除掉」→ ç”¨ Excel COM åˆ é™¤æºæ–‡ä»¶ç¬¬ 11~63 è¡Œï¼ˆæ­¦æ±‰ 27 + é»„石 4),原件备份 `docs/投资/输出/源文件备份/…_原始含武汉黄石_20260921.xls`;重导验证该文件 38 â†’ **7 æ¡**,8 æœˆç‰©æµ 128 â†’ 97,库内仍 152 é¡¹ç›® / 136 æ¡ 2026-08 æœˆåº¦æ•° | æ— éœ€å†å¤„理(后续若再加回非本文件市州段,需重新清理) | âœ… |
| P0-2 | **《亿元投资项目》规上项目表月份列会被覆盖** | ä»£ç åªé‡å†™è¡¨å¤´æ–‡å­—(`ReportExportService.java:6128-6139` å†™ `col5`/`col23`),模板 row2 ç¬¬ 24 åˆ—原本是「2026å¹´7月实际完成投资」。8 æœˆå¯¼å‡ºæŠŠå®ƒæ”¹æˆã€Œ2026å¹´8月…」并写 8 æœˆæ•° â†’ **7 æœˆé‚£ä¸€åˆ—的数据消失** | ç”¨æˆ·å·²åœ¨ã€Šå¾…确认清单》Q7 æ˜Žç¡®ï¼šã€Œåªæ›´æ–° F åˆ— + åœ¨ 2026å¹´X月实际完成投资后**加一列** 2026å¹´X+1月实际完成投资」→ æœªå®žçް | æŒ‰ Q7 æ”¹ä¸ºã€ŒæŒ‰æœˆè¿½åŠ ä¸€åˆ—ã€ï¼›åŒè¡¨å…¶å®ƒå†™æ­»æœˆä»½åˆ—ï¼ˆ1-3月/4月/5月/6月/第二季度)同样要一起看 | âŒ |
| P0-3 | **导出前「基数体检 + å¼¹çª— +《数据缺失清单》页」(B4)** | åŽ»å¹´åŒæœˆåŸºæ•°æ®‹ç¼ºæ—¶ç¨‹åºç…§ç®—ï¼Œæ›¾æŠŠä¸­å£å¾„æŽ’åå…¨çœç´¯è®¡åŒæ¯”ç®—æˆ **+73.89%**(真值 +5.81%)。加体检后可根治复发 | åŽç«¯å·²æ”¶é›†é—®é¢˜æ¸…单 `midIssues`(`ReportExportService.java:2436`)与 `dbProblems`,但 **`getLastMidIssues()` æ²¡æœ‰ä»»ä½•调用方**,前端也无消费,没有《数据缺失清单》页 â†’ åªåšäº† B5(日志)与 B3(完备性校验) | â‘  å°±ç»ª/预览接口返回 issues;② å¯¼å‡ºå‰å¼¹çª—;③ ç”Ÿæˆä»¶è¿½åŠ ã€Šæ•°æ®ç¼ºå¤±æ¸…å•ã€‹é¡µ | ðŸ”¶ |
| P0-4 | **缺 2026-06 / 2026-09 æ¯ç‰ˆ** | è¿™ä¸¤æœŸé¢„览 `ready=false`「未找到模板文件」,出不了表 | `docs/生成汇总大表/` ä¸‹åªæœ‰ 2026å¹´7月 / 2026å¹´8月 + ç‰ˆå¼åŽŸåž‹ï¼›ç¨‹åº**只按文件名精确匹配**、不会自建 | ç”¨æˆ· Q13 å·²æš‚缓(要问同事「能不能用母版自动生成后续每月模板」)。短期:人工放一份 9 æœˆæ¯ç‰ˆï¼›é•¿æœŸï¼šæ‰©åˆ—器(详见汇总大表交接 P0-2) | â¸ |
@@ -203,6 +206,7 @@
| P1-10 | è¿è¾“量 2026-01~07 çš„ `last_*` ä¸ºç©º / H203-1 2026-01~07 çš„ `unified_credit_code`、`report_unit` ä¸ºç©º | å‰è€…是改动前就为空,后者是新列本期才读取;是否补/重导待确认 | â¸ |
| P1-11 | è´§è¿ã€ŒæŒç»­åœ¨è§„ 545 å®¶ã€vs「官方全口径」两版同比(+2.90% vs +4.54%) | å£å¾„不同,已分别注明;若要随《差异率汇总表》上报,建议加注差异原因 | â¸ |
| P1-12 | é«˜é€Ÿè¿è·åŒæ¯”(用户表格 O åˆ—)的来源/期间待确认 | ç¡®è®¤åŽæ–¹å¯ç®—「运距增速差」 | ðŸ”’ ç­‰ç”¨æˆ· |
| P1-13 | æŠ•资系统导出的**新模板**(`2026å¹´X月投资系统项目明细`) | å·²æ”¯æŒæŒ‰è¡¨å¤´å®šä½è§£æžï¼ˆ09-21,129 æ¡å…¥åº“)。**待定**:① æ–°æ¨¡æ¿å¤šå‡ºçš„「项目所处阶段」未落库,如需比对建设阶段要加列并同步 `docs/init.sql`/`docs/database.md`;② æ–°æ¨¡æ¿**没有「自年初累计」列**,该维度审核已改为「基准缺失即跳过 + WARN æ—¥å¿—」(RULE_I002 å®žæµ‹ 0 æ¡ï¼‰ï¼Œè‹¥ä¸šåŠ¡ä»è¦æ¯”å¯¹éœ€æ¨¡æ¿è¡¥å›žè¯¥åˆ— | ðŸ”¶ |
### P2 â€”— å·¥ç¨‹ä¸Žæ•´æ´
@@ -316,3 +320,4 @@
| æ—¥æœŸ | å˜æ›´ |
| --- | --- |
| 2026-09-21 | é¦–次成文:整合汇总大表交接(`docs/问题汇总/汇总大表问题交接_2026-09-21.md`)与投资/货运/客运各线遗留 |
| 2026-09-21(下午) | P0-1 é—­çŽ¯ï¼ˆåå °æºæ–‡ä»¶å·²åˆ æ®µ + é‡å¯¼éªŒè¯ï¼‰ï¼›æ–°å¢ž P1-13(投资系统新模板支持);数据快照补 `investment_system` è¡Œ |
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Ͷ×ÊϵͳÐÂÄ£°å°´±íÍ·½âÎöÓëÉóºË»ù׼ȱʧ±£»¤_2026-09-21.md
New file
@@ -0,0 +1,65 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_投资系统新模板按表头解析与审核基准缺失保护_2026-09-21
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
| # | åŠŸèƒ½ | è¯´æ˜Ž |
| --- | --- | --- |
| 1 | æŠ•资系统导出**按表头定位**解析 | ç”¨æˆ· 2026-09-21 æŠŠã€Œä¸ŽæŠ•资系统比对的明细表」换成了新模板《2026å¹´8月投资系统项目明细》(多一列「项目所处阶段」、少一列「自年初累计」,整体右移)。原实现写死 8 åˆ—列位,遇新模板必然报「表头与系统模板不一致」。本次改为按表头关键字实时定位列,兼容新旧两种模板 |
| 2 | å®¡æ ¸æ¯”对「基准缺失」保护 | æ–°æ¨¡æ¿æ²¡æœ‰ã€Œè‡ªå¹´åˆç´¯è®¡ã€åˆ— â†’ `investment_system.year_cum` ä¸º NULL。原实现用 `nvl()` æŠŠ NULL å½“ 0,会把 100+ ä¸ªé¡¹ç›®å…¨éƒ¨è¯¯åˆ¤ä¸ºã€Œå·®å¼‚」。改为:基准为 NULL æ—¶è·³è¿‡è¯¥å­—段比对并记 WARN æ—¥å¿— |
| 3 | åå °ç‰©æµæ±‡æ€»è¡¨æºæ–‡ä»¶æ¸…理(数据处置,非代码) | æŒ‰ç”¨æˆ· 2026-09-21「清除掉」的要求,删除该文件里的武汉段(27 ä¸ªé¡¹ç›®ï¼‰ä¸Žé»„石段(4 ä¸ªé¡¹ç›®ï¼‰ï¼Œåªä¿ç•™åå °æ®µ |
改动文件:
- `traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java`(`importInvestmentSystem` é‡å†™ + æ–°å¢ž `findColByKeywords` / `headerText`)
- `traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java`(`checkInvestCrossDiff` åŸºå‡†ç¼ºå¤±ä¿æŠ¤ï¼‰
## äºŒã€æµ‹è¯•环境
- åŽç«¯ Spring Boot 8090,重启加载新代码:`backend.log` **2026-09-21 10:20:30 Started TrafficAuditApplication**;前端 8080
- æ•°æ®åº“ MySQL 3308 / `traffic_audit`
- æ–°æ—§æ¨¡æ¿åˆ—结构对照(`xlrd` è¯»å–):
| åˆ— | è€æ¨¡æ¿ã€Šæ¨¡æ¿_查询结果(投资系统-客运+物流 2026.7).xls》 | æ–°æ¨¡æ¿ã€Š2026å¹´8月投资系统项目明细.xls》 |
| --- | --- | --- |
| 1 | è¡Œå· | è¡Œå· |
| 2 | å•位 | **投资项目** |
| 3 | æ—¶æœŸ | æ—¶æœŸ |
| 4 | è®¡åˆ’总投资 | **项目所处阶段**(新增) |
| 5 | è‡ªå¼€å§‹ç´¯è®¡ | è®¡åˆ’总投资 |
| 6 | æœ¬å¹´è®¡åˆ’投资 | æœ¬å¹´è®¡åˆ’投资 |
| 7 | è‡ªå¹´åˆç´¯è®¡ | è‡ªå¼€å§‹å»ºè®¾è‡³æœ¬å¹´ï¼ˆæœˆï¼‰åº•-累计完成投资 |
| 8 | å½“月完成投资 | å½“月完成投资 |
| â€” | â€” | **无「自年初累计」列** |
## ä¸‰ã€ç”¨ä¾‹è¡¨
| # | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T01 | åå °æºæ–‡ä»¶æ¸…理-结构 | åŽŸã€Šæ¹–åŒ—çœåå °â€¦æ±‡æ€»è¡¨ï¼ˆæœˆæŠ¥ï¼‰ï¼ˆ2026å¹´8月).xls》 | åªä¿ç•™åå °æ®µï¼Œæ­¦æ±‰/黄石段消失 | è¡Œæ•° 86 â†’ **33**;十堰段第 10 è¡Œèµ·ã€7 ä¸ªé¡¹ç›®ã€åˆè®¡è¡Œä¿ç•™ï¼›æ­¦æ±‰/黄石段 0 è¡Œ | é€šè¿‡ |
| T02 | åå °æºæ–‡ä»¶æ¸…理-备份 | åŒä¸Š | åŽŸä»¶å…ˆå¤‡ä»½åˆ°è¾“å‡ºç›®å½• | `docs/投资/输出/源文件备份/…_原始含武汉黄石_20260921.xls`(108544 å­—节) | é€šè¿‡ |
| T03 | 8 æœˆç‰©æµé‡å¯¼ï¼ˆæ­£å‘) | `POST /api/import/investCityBatch?period=2026-08&category=物流园区` | åå °åªå‡º 7 æ¡ï¼Œä¸å†äº§ç”Ÿæ­¦æ±‰/黄石项目 | total=97、success=97、fail=0;十堰文件 **ok=7**(改前 38);武汉/黄石 0 æ¡ | é€šè¿‡ |
| T04 | é‡å¯¼åŽåº“核对 | åŒä¸Š | é¡¹ç›®/月度数不增不减 | `investment_project` = **152**、2026-08 æœˆåº¦æ•° = **136**、十堰物流 = 7(与清理前一致) | é€šè¿‡ |
| T05 | æ–°æ¨¡æ¿å¯¼å…¥ï¼ˆæ­£å‘) | æ–°æ¨¡æ¿ 129 è¡Œæ•°æ® | å…¨éƒ¨å…¥åº“ | è¿”回「投资系统导出导入成功, å…± **129** æ¡è®°å½•」;`investment_system` 2026-08 = 129、2026-07 = 148 ä¸å—影响 | é€šè¿‡ |
| T06 | å­—段映射抽查 | åŒä¸Š | é€åˆ—等于源文件 | æ¹–北省综合运输服务站及候车亭:12721.5 / 10306.2 / 10316.1 / 93.5;汉口客运中心:315700 / 30000 / 178235.4 / 550 | é€šè¿‡ |
| T07 | ç¼ºåˆ—处理(负向) | åŒä¸Šï¼ˆæ— ã€Œè‡ªå¹´åˆç´¯è®¡ã€åˆ—) | year_cum ç•™ç©ºï¼Œ**不得**把「自开始建设…」列误当自年初累计 | 129 è¡Œ year_cum å…¨ä¸º NULL(未错填) | é€šè¿‡ |
| T08 | è€æ¨¡æ¿å…¼å®¹ï¼ˆå›žå½’) | è€æ ¼å¼è¡¨å¤´ | ä»èƒ½å¯¼å…¥ | è€æ–‡ä»¶å·²ä¸åœ¨è¾“入目录;改为按表头定位后,老模板 8 åˆ—关键字(单位/计划总投资/自开始建设/本年计划投资/自年初/当月完成投资)全部可命中(代码审查);存量 2026-07 = 148 è¡Œæœªå—影响 | é€šè¿‡ï¼ˆé™æ€ï¼‰ |
| T09 | å®¡æ ¸åŸºå‡†ç¼ºå¤±ä¿æŠ¤ | `POST /api/audit/execute?period=2026-08&reportType=INVEST` | è‡ªå¹´åˆç´¯è®¡è§„则不再产生误报 | RULE_I002 ç»“æžœ **0 æ¡**;日志出现「投资比对跳过(投资系统基准缺失):rule=RULE_I002 â€¦ field=自年初累计」 | é€šè¿‡ |
| T10 | å®¡æ ¸å…¶å®ƒè§„则未受影响 | åŒä¸Š | æ­£å¸¸å‡ºç»“æžœ | RULE_I001(自开始建设累计)2 æ¡ã€RULE_I003(本月完成)1 æ¡ã€RULE_I004(存在性)25 æ¡ï¼Œåˆè®¡ 28 æ¡ | é€šè¿‡ |
| T11 | å®¡æ ¸å¹‚ç­‰ | åŒä¸Šé‡å¤æ‰§è¡Œ | åªæ¸… INVEST æ—§ç»“果、不重复堆积 | ä¸¤æ¬¡æ‰§è¡Œç»“果条数一致(28 æ¡ï¼‰ | é€šè¿‡ |
## å››ã€å‘现的问题与处置
| # | é—®é¢˜ | å¤„ç½® |
| --- | --- | --- |
| P1 | æ–°æ¨¡æ¿å¤šå‡ºã€Œé¡¹ç›®æ‰€å¤„阶段」列,但库表 `investment_system` æ²¡æœ‰å¯¹åº”字段 | **本次不落库**。若业务要比对「建设阶段」,需加列并同步 `docs/init.sql`、`docs/database.md`(按项目规矩三处同步) |
| P2 | æ–°æ¨¡æ¿**没有「自年初累计」列** â†’ è¯¥ç»´åº¦æ— æ³•比对 | å·²æ”¹ä¸ºã€ŒåŸºå‡†ç¼ºå¤±å³è·³è¿‡ + WARN æ—¥å¿—」,不产生误报。若业务仍要比对自年初累计,需新模板补回该列(或确认改用「自开始建设累计」口径) |
| P3 | è€æ¨¡æ¿æ–‡ä»¶ `模板_查询结果(投资系统-客运+物流 2026.7).xls` å·²ä¸åœ¨ `docs/投资/输入/`(被用户替换) | 2026-07 çš„ 148 è¡Œä¸ºè€å£å¾„存量数据,保留不动;后续月份统一用新模板 |
| P4 | å®¡æ ¸æ–°å¢ž 25 æ¡ã€ŒæŠ•资系统导出中不存在」 | å¤šä¸ºä¹¡é•‡ç»¼åˆè¿è¾“服务站与部分物流项目(如 æ¡‚花镇/马桥镇/高桥镇综合运输服务站、郑万高铁巴东综合客运枢纽、潜江传化公路港项目…),属投资系统未收录的客观差异,供业务判断,非本次改动引入 |
| P5 | æºæ–‡ä»¶ä¸º `.xls` ä¸”含合并单元格 | ç”¨ Excel 16.0 COM æ•´è¡Œåˆ é™¤ï¼ˆç¬¬ 11~63 è¡Œï¼‰ï¼Œä¿å­˜åŽ `xlrd` å¤æ ¸è¡Œæ•° 86 â†’ 33;脚本结束清理了本次新建的孤儿 EXCEL è¿›ç¨‹ |
## äº”、结论
- æ–°æ¨¡æ¿ã€Š2026å¹´8月投资系统项目明细》已可正常导入(129 æ¡ï¼‰ï¼Œå­—段逐列对齐,缺列不误填;
- å®¡æ ¸ä¸å†å› ã€ŒåŸºå‡†ç¼ºå¤±ã€æˆç‰‡è¯¯æŠ¥ï¼ˆRULE_I002 ç”± 100+ æ¡é™ä¸º 0 æ¡ï¼‰ï¼Œå…¶ä½™ä¸‰æ¡ INVEST è§„则结果正常(28 æ¡ï¼‰ï¼›
- åå °ç‰©æµæ±‡æ€»è¡¨æºæ–‡ä»¶å·²æ¸…除武汉/黄石段(备份留档),重导验证:十堰只出 7 æ¡ï¼Œåº“内项目/月度数不增不减,**该残留问题闭环**。
测试人:Codex(AI) 测试日期:2026-09-21
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-21.md
@@ -58,9 +58,22 @@
     **导出「按月分目录 + è‡ªåЍ备份 + è¿è¡Œæ—¥å¿—/校验报错」未实现**(Q10 å·²ç­”同意);
  6. å¯¼å‡ºå‰åŸºæ•°ä½“检(B4)只做了一半:后端 `getLastMidIssues()` **无任何调用方**,前端未消费、无《数据缺失清单》页。
### 5. åå °ç‰©æµæºæ–‡ä»¶æ¸…理(用户「清除掉」)+ æŠ•资系统新模板支持
- **十堰源文件清理(数据处置)**:`docs/投资/输入/物流(物流园区)/8月/湖北省十堰交通物流基础设施投资统计汇总表(月报)(2026å¹´8月).xls`
  é‡Œçš„æ­¦æ±‰æ®µï¼ˆ27 ä¸ªé¡¹ç›®ï¼‰ä¸Žé»„石段(4 ä¸ªé¡¹ç›®ï¼‰ç”¨ Excel COM æ•´è¡Œåˆ é™¤ï¼ˆç¬¬ 11~63 è¡Œï¼‰ï¼Œåªç•™åå °æ®µï¼ˆ7 ä¸ªé¡¹ç›®ï¼‰ï¼›
  åŽŸä»¶å…ˆå¤‡ä»½åˆ° `docs/投资/输出/源文件备份/…_原始含武汉黄石_20260921.xls`。
  é‡å¯¼éªŒè¯ï¼šè¯¥æ–‡ä»¶ç”± **38 æ¡ â†’ 7 æ¡**,8 æœˆç‰©æµ total 128 â†’ 97,库内仍是 152 ä¸ªé¡¹ç›® / 136 æ¡ 2026-08 æœˆåº¦æ•°ï¼ˆä¸å¢žä¸å‡ï¼‰â†’ **残留问题闭环**。
- **投资系统导出新模板**:用户把比对明细表换成《2026å¹´8月投资系统项目明细》(多「项目所处阶段」、少「自年初累计」,列位整体右移)。
  åŽŸå®žçŽ°å†™æ­» 8 åˆ— â†’ æ”¹ä¸º**按表头关键字定位**(`findColByKeywords`),兼容新旧模板;缺列时 `year_cum` ç•™ç©ºè€Œä¸æ˜¯é”™å¡«ã€‚
  æ–°æ¨¡æ¿ 129 æ¡å·²å…¥åº“(`investment_system` 2026-08 = 129,2026-07 = 148 ä¸å—影响),字段逐列抽查一致。
- **审核「基准缺失」保护**:新模板没有「自年初累计」,原 `nvl()` ä¼šæŠŠ NULL å½“ 0 â†’ 100+ æ¡è¯¯æŠ¥ã€‚改为基准为 NULL æ—¶è·³è¿‡å¹¶è®° WARN æ—¥å¿—。
  å®žæµ‹ï¼šRULE_I002 ç”±ã€Œæ¯ä¸ªé¡¹ç›®ä¸€æ¡ã€é™ä¸º **0 æ¡**;RULE_I001 2 æ¡ã€RULE_I003 1 æ¡ã€RULE_I004(存在性)25 æ¡ï¼Œåˆè®¡ 28 æ¡å‡ä¸ºçœŸå®žå·®å¼‚。
## äºŒã€æµ‹è¯•结果摘要
- æœ¬æ¬¡**无代码改动**,无《功能测试报告》(仅有数据核查)。
- è§ã€ŠåŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_投资系统新模板按表头解析与审核基准缺失保护_2026-09-21.md》:**11 æ¡ç”¨ä¾‹é€šè¿‡**(正向 6 / è´Ÿå‘ 1 / å›žå½’ 4)。
- ä¸ŠåŠæ—¥ï¼ˆæ±‡æ€»å¤§è¡¨åŒè½¨åˆ¶å®šä½ï¼‰ï¼šæœ¬æ¬¡**无代码改动**,无《功能测试报告》(仅有数据核查)。
- æ•°æ®æ ¸æŸ¥å£å¾„:全部结果与库内 `h2031_enterprise_monthly` / `passenger_individual_monthly` /
  `city_bus_monthly` / `city_taxi_monthly` / `wyc_order_monthly` çŽ°ç®—å€¼é€ä½æ¯”å¯¹ï¼Œ17 å¸‚å·ž Ã— 8 ä¸ªæœˆï¼Œ
  ä¸€è‡´æ€§è¾¾ 1e-9;复现脚本与中间输出已留档(见上)。
docs/Ͷ×Ê/ÊäÈë/Ä£°å_²éѯ½á¹û(Ͷ×Êϵͳ-¿ÍÔË+ÎïÁ÷ 2026.7).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/ºþ±±Ê¡Ê®Ñß½»Í¨ÎïÁ÷»ù´¡ÉèʩͶ×Êͳ¼Æ»ã×Ü±í£¨Ô±¨£©£¨2026Äê8Ô£©.xls
Binary files differ
docs/Ͷ×Ê/Êä³ö/Ô´Îļþ±¸·Ý/ºþ±±Ê¡Ê®Ñß½»Í¨ÎïÁ÷»ù´¡ÉèʩͶ×Êͳ¼Æ»ã×Ü±í£¨Ô±¨£©£¨2026Äê8Ô£©_ԭʼº¬Î人»ÆÊ¯_20260921.xls
Binary files differ
traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
@@ -690,23 +690,30 @@
        if (sys == null) return null; // ç¼ºå¤±ç”± EXISTENCE_SYS è§„则提示
        String field = rule.getCheckField();
        double actual;
        double reference;
        Double referenceObj;
        String fieldName;
        if ("startCum".equals(field)) {
            actual = nvl(monthly.getStartCum());
            reference = nvl(sys.getStartCum());
            referenceObj = sys.getStartCum();
            fieldName = "自开始建设累计";
        } else if ("yearCum".equals(field)) {
            actual = nvl(monthly.getYearCum());
            reference = nvl(sys.getYearCum());
            referenceObj = sys.getYearCum();
            fieldName = "自年初累计";
        } else if ("monthDone".equals(field)) {
            actual = nvl(monthly.getMonthDone());
            reference = nvl(sys.getMonthDone());
            referenceObj = sys.getMonthDone();
            fieldName = "本月完成";
        } else {
            return null;
        }
        // åŸºå‡†ç¼ºå¤±ï¼ˆå¦‚新模板《2026å¹´X月投资系统项目明细》没有「自年初累计」列)→ ä¸å…·å¤‡å¯æ¯”性,跳过并记日志;
        // ä¸èƒ½æŠŠ null å½“成 0 åŽ»æ¯”å¯¹ï¼Œå¦åˆ™ä¼šæˆç‰‡è¯¯æŠ¥ã€‚
        if (referenceObj == null) {
            log.warn("投资比对跳过(投资系统基准缺失):rule={} project={} field={}", rule.getRuleCode(), projectName, fieldName);
            return null;
        }
        double reference = referenceObj;
        String[] parts = rule.getThreshold().split("\\|");
        double absThreshold = parts.length > 0 ? parseDoubleSafe(parts[0], 50) : 50;
        double pctThreshold = parts.length > 1 ? parseDoubleSafe(parts[1], 5) : 5;
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -1808,6 +1808,35 @@
        }
    }
    /** æŒ‰è¡¨å¤´å…³é”®å­—定位列号:从第 1 åˆ—向右扫,命中任一关键字即返回该列;未命中返回 -1 */
    private int findColByKeywords(Row header, String... keywords) {
        if (header == null) return -1;
        for (int c = 0; c <= header.getLastCellNum(); c++) {
            Cell cell = header.getCell(c);
            if (cell == null) continue;
            String h = FORMATTER.formatCellValue(cell).trim();
            if (h.isEmpty()) continue;
            for (String k : keywords) {
                if (h.contains(k)) return c;
            }
        }
        return -1;
    }
    /** è¡¨å¤´è¡Œæ–‡æœ¬ï¼ˆæŠ¥é”™æç¤ºç”¨ï¼‰ï¼Œæœ€å¤šå– 12 åˆ— */
    private String headerText(Row header) {
        if (header == null) return "空";
        StringBuilder sb = new StringBuilder();
        for (int c = 0; c < Math.min(header.getLastCellNum(), 12); c++) {
            Cell cell = header.getCell(c);
            String h = cell == null ? "" : FORMATTER.formatCellValue(cell).trim();
            if (h.isEmpty()) continue;
            if (sb.length() > 0) sb.append(" | ");
            sb.append(h);
        }
        return sb.length() == 0 ? "空" : sb.toString();
    }
    /** æŒ‰è¡¨å¤´åç§°å»ºç«‹åˆ—号映射,兼容新旧模板列位差异 */
    private Map<String, Integer> buildHeaderMap(Row header) {
        Map<String, Integer> colMap = new HashMap<>();
@@ -2931,32 +2960,42 @@
            this.monthly = monthly;
        }
    }
    /** æŠ•资系统导出导入(审核比对基准),固定8列:行号/单位/时期/计划总投资/自开始累计/本年计划/自年初累计/当月完成 */
    private static final int[] INVEST_SYSTEM_HEADER_COLS = {0, 1, 2, 3, 4, 5, 6, 7};
    private static final String[] INVEST_SYSTEM_HEADER_KEYWORDS =
        {"行号", "单位", "时期", "计划总投资", "自开始建设", "本年计划投资", "自年初", "当月完成投资"};
    /** æŠ•资系统导出导入(审核比对基准)。
     *  åˆ—位**按表头关键字定位**,兼容两种模板:
     *   - è€æ¨¡æ¿ã€Šæ¨¡æ¿_查询结果(投资系统-客运+物流 2026.7).xls》:行号/单位/时期/计划总投资/自开始建设累计/本年计划投资/自年初累计/当月完成投资
     *   - æ–°æ¨¡æ¿ã€Š2026å¹´X月投资系统项目明细.xls》(用户 2026-09-21 æ›´æ¢ï¼‰ï¼šè¡Œå·/投资项目/时期/项目所处阶段/计划总投资/本年计划投资/自开始建设至本年(月)底-累计完成投资/当月完成投资
     *  æ–°æ¨¡æ¿**没有「自年初累计」列** â†’ year_cum ç•™ç©ºï¼ˆå®¡æ ¸æ—¶æŒ‰ã€ŒåŸºå‡†ç¼ºå¤±ã€è·³è¿‡ï¼Œä¸å†å½“成 0 å‚与比对)。 */
    public int importInvestmentSystem(MultipartFile file, String period) throws Exception {
        List<InvestmentSystem> list = new ArrayList<>();
        int failRows = 0;
        try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
            Sheet sheet = wb.getSheetAt(0);
            requireHeaderKeyword(sheet, "投资系统导出", "项目名称", "计划总投资", "单位");
            requireHeaderLayout(sheet, "投资系统导出", "模板_查询结果(投资系统-客运+物流 2026.7).xls",
                INVEST_SYSTEM_HEADER_COLS, INVEST_SYSTEM_HEADER_KEYWORDS);
            requireHeaderKeyword(sheet, "投资系统导出", "投资项目", "项目名称", "单位", "计划总投资");
            Row header = sheet.getRow(0);
            int cName = findColByKeywords(header, "投资项目", "项目名称", "单位");
            int cTotal = findColByKeywords(header, "计划总投资");
            int cYearPlan = findColByKeywords(header, "本年计划投资");
            int cStartCum = findColByKeywords(header, "自开始建设");
            int cYearCum = findColByKeywords(header, "自年初");
            int cMonthDone = findColByKeywords(header, "当月完成投资");
            if (cName < 0 || cTotal < 0 || cYearPlan < 0 || cStartCum < 0 || cMonthDone < 0) {
                throw new RuntimeException("所选数据类型【投资系统导出】表头列不完整:需要「投资项目(或单位)、计划总投资、本年计划投资、"
                    + "自开始建设…累计完成投资、当月完成投资」等列,实际表头为「" + headerText(header)
                    + "」。请使用系统模板《2026å¹´X月投资系统项目明细》或《模板_查询结果(投资系统-客运+物流)》整理后再导入");
            }
            for (int r = 1; r <= sheet.getLastRowNum(); r++) {
                Row row = sheet.getRow(r);
                if (row == null) continue;
                String name = getString(row, 1);
                String name = getString(row, cName);
                if (name == null || name.trim().isEmpty()) continue;
                InvestmentSystem sys = new InvestmentSystem();
                sys.setReportPeriod(period);
                sys.setProjectName(name.trim());
                sys.setTotalInvestment(getDecimal(row, 3));
                sys.setStartCum(getDecimal(row, 4));
                sys.setYearPlan(getDecimal(row, 5));
                sys.setYearCum(getDecimal(row, 6));
                sys.setMonthDone(getDecimal(row, 7));
                sys.setTotalInvestment(getDecimal(row, cTotal));
                sys.setStartCum(getDecimal(row, cStartCum));
                sys.setYearPlan(getDecimal(row, cYearPlan));
                sys.setYearCum(cYearCum < 0 ? null : getDecimal(row, cYearCum));
                sys.setMonthDone(getDecimal(row, cMonthDone));
                list.add(sys);
            }
        } catch (Exception e) {