From be562b28a259e2eb5bf93dc7dcb3172ed3891e19 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期二, 08 九月 2026 10:54:09 +0800
Subject: [PATCH] feat: 汇总大表数据驱动 M1-班线包车——新增 MidCalc 计算服务(企业+个体口径)与 7 月回归测试报告

---
 docs/工作日结/工作日结_2026-09-08.md                                                       |   23 +++++--
 traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/MidCalc.java |  110 ++++++++++++++++++++++++++++++++++++
 docs/功能测试报告/功能测试报告_M1-班线包车MidCalc_2026-09-08.md                                    |   44 ++++++++++++++
 3 files changed, 169 insertions(+), 8 deletions(-)

diff --git "a/docs/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212_M1-\347\217\255\347\272\277\345\214\205\350\275\246MidCalc_2026-09-08.md" "b/docs/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212_M1-\347\217\255\347\272\277\345\214\205\350\275\246MidCalc_2026-09-08.md"
new file mode 100644
index 0000000..67ff271
--- /dev/null
+++ "b/docs/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212_M1-\347\217\255\347\272\277\345\214\205\350\275\246MidCalc_2026-09-08.md"
@@ -0,0 +1,44 @@
+# 鍔熻兘娴嬭瘯鎶ュ憡锛歁1-鐝嚎鍖呰溅锛圡idCalc 浼佷笟+涓綋鍙栨暟锛変笌 7 鏈堝洖褰掞紙2026-09-08锛�
+
+## 涓�銆佸姛鑳借鏄�
+姹囨�诲ぇ琛ㄦ暟鎹┍鍔ㄦ敼閫� M1 绗簲鍧楋細鎶娾�滅彮绾垮寘杞﹂〉鈥濈殑鏁版嵁搴撳彇鏁板浐鍖栦负鍙鐢� Java 璁$畻鏈嶅姟
+`MidCalc`锛坄traffic-audit-server/.../reportexport/calc/MidCalc.java`锛夛紝杈撳嚭
+鈥滄湀 鈫� 甯傚窞/鍏ㄧ渷 鈫� [瀹㈣繍閲�(鍚釜浣�), 鍛ㄨ浆閲�(鍚釜浣�), 涓綋瀹㈣繍閲�, 涓綋鍛ㄨ浆閲廬锛堜竾浜�/涓囦汉鍏噷锛夆�濄��
+瀹冩槸涓彛寰勬槑缁�/鎺掑悕/鍒嗘瀽/閬撹矾杩愯緭鍛ㄨ浆閲忕瓑娲剧敓椤靛湪鏁版嵁搴撲腑鍞竴鐨勫叕璺彮绾挎暟鎹簮銆�
+
+## 浜屻�佹祴璇曠幆澧�
+- 搴擄細`traffic_audit`锛�127.0.0.1:3308锛夛紝鏁版嵁 = 2026-01~07 宸插鍏ョ幇鐘讹紱
+- 姣嶇増鍩虹嚎锛歚docs/鐢熸垚姹囨�诲ぇ琛�/_澶囦唤_2026骞�7鏈堥亾璺繍杈撻噺姹囨�昏〃_娓呯悊鍓峗20260904.xlsx`锛堢彮绾垮寘杞﹂〉锛�2026 鏈堝害鏁板�煎垪 C/E/G/I/K/M/O 鍧囧凡缂撳瓨锛夛紱
+- 宸ュ叿锛歮ysql CLI 鍙栨暟 + Python 閫愭牸姣斿锛坄_m1_mid_regress.py`锛岀粨鏋� `_m1_mid_regress.txt`锛夛紱鍚庣 `mvn -q -DskipTests compile` 閫氳繃锛坋xit=0锛夈��
+
+## 涓夈�佸彇鏁板彛寰勶紙缁忔瘝鐗堥�愭牸鍙嶆帹纭锛�2026-07 涓� 1-7 鏈堝叏閮ㄥ懡涓級
+| 姣嶇増琛� | 鍙e緞 | 鏉ユ簮 |
+|---|---|---|
+| 瀹㈣繍閲� / 鏃呭鍛ㄨ浆閲忥紙涓囦汉 / 涓囦汉鍏噷锛� | **浼佷笟鎬昏 + 涓綋骞跺叆** | `h2031_enterprise_monthly.passenger_total / turnover_total`锛堜汉/浜哄叕閲岋級梅10000锛屽彔鍔� `passenger_individual_monthly.passenger_count / turnover` 梅10000 |
+| 鍏朵腑锛氫釜浣撳杩愰噺 / 涓綋鏃呭鍛ㄨ浆閲� | 涓綋鏁� 梅10000 | 浠呴粍鐭�/瑗勯槼/鑽嗛棬/瀛濇劅/榛勫唸/闅忓窞 6 甯傛湁鏁� |
+| 婀栧寳鐪侊紙鍏ㄧ渷锛夎 | 17 甯傚窞涔嬪拰 | 涓庢瘝鐗堚�滃叏鐪佽=危鍩庡競琛屸�濆叕寮忎竴鑷� |
+| 鍚屾瘮 | 涓嶈绠� | Q1锛氫互姣嶇増缂撳瓨 2025 鍙傜収缁勪负鍩哄噯锛岀敱鍐欏洖灞傚~琛ㄦ椂璁$畻 |
+
+## 鍥涖�佺敤渚嬭〃
+| # | 鐢ㄤ緥 | 杈撳叆 | 棰勬湡 | 瀹為檯 | 缁撹 |
+|---|---|---|---|---|---|
+| 1 | 浼佷笟瀹㈣繍閲�/鍛ㄨ浆閲忥紙鍚釜浣撳苟鍏ワ級 | 搴� 2026-01~07 | 涓庢瘝鐗堢彮绾垮寘杞﹀煄甯傝鈥滃杩愰噺/鍛ㄨ浆閲忊�濆垪閫愭牸涓�鑷� | 350 鏍� diff=0 | 閫氳繃 |
+| 2 | 鍏朵腑涓綋瀹㈣繍閲�/鍛ㄨ浆閲� | 搴� 2026-01~07 | 涓庢瘝鐗堚�滃叾涓釜浣撯�濊閫愭牸涓�鑷达紙6 甯傦級 | 鍚簬涓婅堪 350 鏍硷紝diff=0 | 閫氳繃 |
+| 3 | 婀栧寳鐪佽 = 危 17 甯傚窞 | 搴撴眹鎬� | 涓庢瘝鐗堝叕寮忓彛寰勪竴鑷� | 涓�鑷� | 閫氳繃 |
+| 4 | 涓彛寰勫垎鏋愨�滃叕璺彮绾库�濋敋鐐� | 搴� 2026-07 / 1-7 绱 | 褰撴湀 1631.2013銆佺疮璁� 11204.5406锛堟瘝鐗堢紦瀛樺�硷級 | 1612.2015+18.9998=1631.2013锛�11062.7993+141.7413=11204.5406 | 閫氳繃 |
+| 5 | 鍩庨檯鍩庝埂鍏氦/鍑虹/缃戠害娲剧敓椤甸敋鐐� | 姣嶇増婧愰〉 O 鍒�/绱鍒� | 涓庝腑鍙e緞鍒嗘瀽缂撳瓨涓�鑷� | 鍏氦褰撴湀 1466.66銆佸嚭绉� 509銆佺綉绾� 421.46 鍏ㄤ腑锛堢疮璁″叕浜よ闂 2锛� | 閮ㄥ垎鍛戒腑 |
+| 6 | Java 缂栬瘧 | `mvn -q -DskipTests compile` | 鏃犻敊璇� | exit=0 | 閫氳繃 |
+
+## 浜斻�佸彂鐜扮殑闂涓庡缃�
+1. 鍒濈増鍥炲綊璇妸鈥滃杩愰噺鈥濊褰撲綔绾紒涓氭暟锛屾瘮瀵瑰彂鐜伴粍鐭崇瓑 6 甯傛瘝鐗堝�� = 浼佷笟+涓綋锛堝樊閲忔伆涓鸿甯備釜浣撳�硷級锛�
+   缁忛�愭牸鍙嶆帹纭**鐝嚎鍖呰溅鈥滃杩愰噺/鍛ㄨ浆閲忊�濆彛寰勫惈涓綋**锛屸�滃叾涓釜浣撯�濊涓哄叾瀛愰泦 鈫� 宸叉寜鍚釜浣撳彛寰勫疄鐜板苟澶嶈窇 0 宸紓銆�
+2. 姣嶇増鍐呴儴涓嶄竴鑷达紙闈炴湰娆′唬鐮侀棶棰橈紝璁板叆寰呭姙锛夛細涓彛寰勫垎鏋愰〉鈥滅疮璁″煄闄呭煄涔″叕浜�=10194.09鈥濓紝
+   涓庢瘝鐗堝叕浜ゅ彴璐﹂〉 1-7 鏈堝煄闄呭煄涔¢�愭湀姹傚拰 8676.57 涓嶇锛堝樊 1517.52锛夛紝鐤戜负璇ラ〉鏃ц绠楁畫鍊硷紱
+   褰撴湀鍚勬淳鐢熼〉閿氱偣涓庢簮椤典竴鑷淬�傚缃細M2 浠ユ簮椤碉紙鏈湇鍔�+宸查獙鏀剁殑 Pax/Wyc 鏈嶅姟锛夋暟鍊奸噸绠楁垚鍝侀〉鍚庡楠屻��
+3. 涓彛寰勬帓鍚嶉〉褰撴湀/绱鏁板�兼棤娉曠敤姣嶇増婧愰〉褰撳墠鏁板�艰В閲婏紙閮ㄥ垎甯傚窞宸噺鎭掑畾锛夛紝鍒ゅ畾鍚屼负鏃ц绠楁畫鍊硷紝
+   闅� M2 鎴愬搧椤甸噸绠椾竴骞舵牳瀵癸紝涓嶅湪 M1 鍙栨暟灞傚鐞嗐��
+
+## 鍏�佺粨璁轰笌涓嬩竴姝�
+- 缁撹锛氱彮绾垮寘杞﹂〉鍙粠搴撳畬鏁村绠楋紙350 鏍� 0 宸紓锛夛紝鍙e緞閿佸畾锛沗MidCalc` 宸插叆搴撳苟閫氳繃缂栬瘧銆�
+- 涓嬩竴姝ワ細鈶� M1 鍓╀綑娲剧敓椤靛彛寰勬牳瀵癸紙鎺掑悕/鍒嗘瀽/閬撹矾杩愯緭鍛ㄨ浆閲忥紝寤鸿闅� M2 閲嶇畻瀹炵幇锛夛紱鈶� M2 SummaryFiller
+  鍐欏洖鍙拌处+鎴愬搧椤靛苟閫愭牸 diff锛堝惈鏈姤鍛婇棶棰� 2/3 鐨勪慨澶嶉獙璇侊級锛涒憿 8 鏈堝疄寮广��
diff --git "a/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-08.md" "b/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-08.md"
index 8be839d..18c57d1 100644
--- "a/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-08.md"
+++ "b/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-08.md"
@@ -6,15 +6,22 @@
    - 鎵ц椤哄簭鎸� E1锛氬厛鍥炲綊 7 鏈堛�佸啀濉� 8 鏈堬紱
    - 璐ц繍/鍏矾鏃呭/鍩庡競瀹㈣繍涓夌被鐙珛灏忚〃鍓嶇鍏ㄩ儴闅愯棌锛屽唴閮ㄤ腑闂磋〃淇濈暀锛�
    - 纭珛绾緥锛氫互鍥炴墽鏂囨。涓哄敮涓�鍐崇瓥鍩虹嚎锛屽凡纭椤逛笉鍐嶉噸澶嶆彁闂��
-2. 鍚姩 M0锛堟寜闇�鎵╁垪锛夊疄鐜板噯澶囷細鍒嗘瀽姣嶇増鍙拌处椤碘��2026-07 鈫� 2026-08 鎵╁垪鈥濆奖鍝嶉潰锛堝緟琛ュ厖缁撴灉锛夈��
+2. M0 褰卞搷闈㈠疄娴嬩笌瀹炵幇绛栫暐锛堟寜闇�鎵╁垪锛�10 闀胯〃椤甸�愭湀鎵╁垪銆佹垚鍝侀〉涓嶆墿锛夆�斺�旇 `docs/姹囨�诲ぇ琛ㄦ暟鎹┍鍔ㄦ敼閫犳柟妗堚� 闄勫綍銆�
+3. M1 璁$畻鏈嶅姟鎶藉彇涓� 7 鏈堝洖褰掞紙閫愬潡娴嬭瘯鎶ュ憡瑙� `docs/鍔熻兘娴嬭瘯鎶ュ憡/`锛屽潎 0 宸紓锛夛細
+   - M1-璐ц繍锛氭柊澧� `FreightCalc`锛堣涓�/瑙勪笅/鍚堣 脳 璐ц繍閲�/鍛ㄨ浆閲� 脳 褰撴湀/绱锛夛紱
+   - M1-鍩庡競瀹㈣繍锛氭柊澧� `PaxCalc`锛堝叕浜�/鍑虹/杞ㄩ亾杞浮鍙拌处椤碉級锛�
+   - M1-缃戠害杞︼細鏂板 `WycSplitCalc`锛�17 甯傚窞鎷嗗垎 + 鍏ㄧ渷 pin锛夛紱
+   - M1-鍩庡競瀹㈣繍鏁撮摼鍥炲綊锛堝煄甯傛眹鎬婚〉褰撴湀 r14-20銆佺疮璁� r3-9 0 宸紓锛夛紱
+   - M1-鐝嚎鍖呰溅锛氭柊澧� `MidCalc`锛坔2031 浼佷笟鎬昏 + 涓綋骞跺叆鍙e緞锛�350 鏍� 0 宸紓锛夈��
 
 ## 娴嬭瘯缁撴灉鎽樿
-- 鏃犱唬鐮佹敼鍔紙鏂囨。淇闃舵锛夈��
+- 浜斾釜 M1 鍧楀悇鑷� 7 鏈堝洖褰� 0 宸紓骞堕�氳繃 `mvn -q -DskipTests compile`锛坋xit=0锛夈��
+- 鍥炲綊涓彂鐜版瘝鐗堟垚鍝侀〉鏃ц绠楁畫鍊硷紙璁板緟鍔烇級锛氫腑鍙e緞鍒嗘瀽鈥滅疮璁″煄闄呭煄涔″叕浜� 10194.09鈥濅笌鍏氦鍙拌处椤� 1-7 鏈堟眰鍜� 8676.57 涓嶇锛�
+  涓彛寰勬帓鍚嶉〉鏁板�间害涓庢瘝鐗堟簮椤靛綋鍓嶆暟鍊间笉涓�鑷粹�斺�斿垽瀹� M2 閲嶇畻鎴愬搧椤垫椂涓�骞朵慨澶嶆牳瀵广��
 
 ## 閬楃暀闂涓庡緟鍔�
-- M0锛氭寜闇�鎵╁垪瀹炵幇锛堝綋鏈堝�煎垪+鍚屾瘮鍒楁彃鍏ョ疮璁″墠銆佺疮璁℃粴鍔ㄣ��2025+ 鍙傜収缁勫彸绉伙級鈥斺�斿奖鍝嶉潰鍒嗘瀽涓紱
-- M1锛氳绠楁湇鍔℃娊鍙栦笌 7 鏈堝璐︼紱M2锛歋ummaryFiller 鍥炲綊 7 鏈堬紱M3锛�8 鏈堝疄寮癸紱M4锛氬皬琛ㄥ墠绔殣钘�+鍒犲浠借繕鍘熴��
-
-### 杩藉姞锛歁0 褰卞搷闈㈠疄娴嬩笌瀹炵幇绛栫暐锛堟櫄闂达級
-- 瀹炴祴纭闇�閫愭湀鎵╁垪鐨勯〉=10 涓暱琛ㄩ〉锛堣揣杩�/鐝嚎鍖呰溅/鍏矾鎬诲杩�/鍩庡競瀹㈣繍/鍏氦/鍑虹/缃戠害杞�/杞ㄩ亾杞浮/涓彛寰勬槑缁�/涓彛寰勫杩愰噺锛夛紱6 涓垚鍝侀〉+璁$畻椤典笉鎵╁垪銆�
-- M0 瀹氭锛氬疄鐜扳�滄湀搴︾増寮忛噸寤哄櫒鈥濓紙鍒楀竷灞�鍙傛暟鍖栨寜鐩爣鏈堥噸寤猴紝闈� POI 灏卞湴骞崇Щ锛夛紝璇﹁鏂规闄勫綍銆�
+- M0锛氭湀搴︾増寮忛噸寤哄櫒锛堟寜闇�鎵╁垪锛夊疄鐜帮紱
+- M1锛氭淳鐢熼〉锛堜腑鍙e緞鏄庣粏/鎺掑悕/鍒嗘瀽/閬撹矾杩愯緭鍛ㄨ浆閲�/鍏矾鎬诲杩愶級鍙e緞鏍稿寤鸿骞跺叆 M2 鎴愬搧椤甸噸绠椾竴骞堕獙璇侊紱
+- M2锛歋ummaryFiller 鍐欏洖鍙拌处椤�+鎴愬搧椤碉紝閫愭牸 diff锛堝惈鏈棩鈥滄棫璁$畻娈嬪�尖�濅慨澶嶉獙璇侊級锛�
+- M3锛�8 鏈堝疄寮癸紙鍏堟墿鍒� 2026-08锛屽啀瀵煎叆 8 鏈堟暟鎹敓鎴愶級锛�
+- M4锛氬皬琛ㄥ墠绔殣钘� + 澶囦唤杩樺師/娓呯悊銆�
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/MidCalc.java b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/MidCalc.java
new file mode 100644
index 0000000..66a477e
--- /dev/null
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/MidCalc.java
@@ -0,0 +1,110 @@
+package com.trafficaudit.reportexport.calc;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.trafficaudit.common.util.RegionUtil;
+import com.trafficaudit.dataimport.entity.PassengerEnterpriseMonthly;
+import com.trafficaudit.dataimport.entity.PassengerIndividualMonthly;
+import com.trafficaudit.dataimport.mapper.PassengerEnterpriseMonthlyMapper;
+import com.trafficaudit.dataimport.mapper.PassengerIndividualMonthlyMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鍏矾鐝嚎锛堝惈涓綋锛夊彛寰勮绠楁湇鍔★紙姹囨�诲ぇ琛ㄦ暟鎹┍鍔ㄦ敼閫� M1-鐝嚎鍖呰溅锛�2026-09-08锛夈��
+ *
+ * 鍙e緞锛�2026-07 涓� _澶囦唤_2026骞�7鏈堥亾璺繍杈撻噺姹囨�昏〃_娓呯悊鍓峗20260904.xlsx 鐝嚎鍖呰溅椤�
+ * 浼佷笟/涓綋琛� 1-7 鏈堥�愭牸鍥炲綊 0 宸紓锛�350 鏍煎叏涓級锛�
+ * 1. 鐝嚎鍖呰溅椤碘�滃杩愰噺/鏃呭鍛ㄨ浆閲忊�濊 = h2031_enterprise_monthly 鎸� 17 甯傚窞姹囨��
+ *    锛坧assenger_total / turnover_total锛屼汉 / 浜哄叕閲岋級闄や互 10000锛屽啀骞跺叆涓綋瀹㈣繍
+ *    锛坧assenger_individual_monthly 鍚屽彛寰勶級锛涒�滃叾涓釜浣撳杩愰噺/鍛ㄨ浆閲忊�濊 = 涓綋鏁伴櫎浠� 10000
+ *    锛堝綋鍓嶄粎榛勭煶/瑗勯槼/鑽嗛棬/瀛濇劅/榛勫唸/闅忓窞鏈夋暟锛夈��
+ * 2. 鍏ㄧ渷琛� = 17 甯傚窞涔嬪拰锛屼笌姣嶇増鈥滃叏鐪佽=鍩庡競琛屾眰鍜屸�濆叕寮忎竴鑷达紱涓彛寰勫垎鏋愰〉鈥滃叕璺彮绾库��
+ *    = 鏈彛寰勫叏鐪佸悎璁★紙褰撴湀 1631.2013銆佺疮璁� 11204.5406 涓庢瘝鐗� 0 宸紓锛夈��
+ * 3. 鍚屾瘮浠ユ瘝鐗堢紦瀛� 2025 鍙傜収缁勪负鍩哄噯锛圦1锛夛紝涓嶅湪鏈湇鍔¤绠椼��
+ *
+ * 杈撳嚭锛氭湀 鈫� 甯傚窞锛堝惈 PROVINCE=婀栧寳鐪侊級 鈫� double[4] =
+ * [瀹㈣繍閲�(鍚釜浣�), 鍛ㄨ浆閲�(鍚釜浣�), 涓綋瀹㈣繍閲�, 涓綋鍛ㄨ浆閲廬锛�
+ * 鍗曚綅鍧囦负姣嶇増灞曠ず鍙e緞锛堜竾浜� / 涓囦汉鍏噷锛夛紱浼佷笟鍗曠嫭閲� = arr[0]-arr[2] 涓� arr[1]-arr[3]銆�
+ */
+@Service
+public class MidCalc {
+
+    public static final String PROVINCE = "婀栧寳鐪�";
+
+    @Resource
+    private PassengerEnterpriseMonthlyMapper passengerMapper;
+    @Resource
+    private PassengerIndividualMonthlyMapper individualMapper;
+
+    /** 鐝嚎鍖呰溅椤垫暟鍊肩煩闃碉細鏈� 鈫� 甯傚窞/鍏ㄧ渷 鈫� [瀹㈣繍閲�,鍛ㄨ浆閲�,涓綋瀹㈣繍閲�,涓綋鍛ㄨ浆閲廬 */
+    public Map<Integer, Map<String, double[]>> banxianMonthly(String yearPrefix, int limit) {
+        Map<Integer, Map<String, double[]>> result = new LinkedHashMap<>();
+        List<PassengerEnterpriseMonthly> entRows = passengerMapper.selectList(
+            new LambdaQueryWrapper<PassengerEnterpriseMonthly>().likeRight(
+                PassengerEnterpriseMonthly::getReportPeriod, yearPrefix));
+        for (PassengerEnterpriseMonthly r : entRows) {
+            int m = monthOf(r.getReportPeriod());
+            if (m < 1 || m > limit) continue;
+            String city = RegionUtil.cityByCode(r.getRegionCode());
+            if (city == null) continue;
+            double pax = nz(r.getPassengerTotal());
+            double turn = nz(r.getTurnoverTotal());
+            if (pax == 0.0 && turn == 0.0) {
+                pax = nz(r.getPassengerClass1()) + nz(r.getPassengerClass2())
+                    + nz(r.getPassengerClass3()) + nz(r.getPassengerClass4())
+                    + nz(r.getPassengerCharter());
+                turn = nz(r.getTurnoverClass1()) + nz(r.getTurnoverClass2())
+                    + nz(r.getTurnoverClass3()) + nz(r.getTurnoverClass4())
+                    + nz(r.getTurnoverCharter());
+            }
+            accumulate(result, m, city, pax / 10000.0, turn / 10000.0, 0.0, 0.0);
+        }
+        List<PassengerIndividualMonthly> indRows = individualMapper.selectList(
+            new LambdaQueryWrapper<PassengerIndividualMonthly>().likeRight(
+                PassengerIndividualMonthly::getReportPeriod, yearPrefix));
+        for (PassengerIndividualMonthly r : indRows) {
+            int m = monthOf(r.getReportPeriod());
+            if (m < 1 || m > limit) continue;
+            String city = RegionUtil.cityByCode(r.getRegionCode());
+            if (city == null) continue;
+            double pax = nz(r.getPassengerCount()) / 10000.0;
+            double turn = nz(r.getTurnover()) / 10000.0;
+            accumulate(result, m, city, pax, turn, pax, turn);
+        }
+        return result;
+    }
+
+    private void accumulate(Map<Integer, Map<String, double[]>> result, int m, String city,
+                            double paxAll, double turnAll, double paxIndi, double turnIndi) {
+        Map<String, double[]> monthMap = result.computeIfAbsent(m, k -> new HashMap<>());
+        add(monthMap.computeIfAbsent(city, k -> new double[4]), paxAll, turnAll, paxIndi, turnIndi);
+        add(monthMap.computeIfAbsent(PROVINCE, k -> new double[4]), paxAll, turnAll, paxIndi, turnIndi);
+    }
+
+    private void add(double[] arr, double paxAll, double turnAll, double paxIndi, double turnIndi) {
+        arr[0] += paxAll;
+        arr[1] += turnAll;
+        arr[2] += paxIndi;
+        arr[3] += turnIndi;
+    }
+
+    private int monthOf(String reportPeriod) {
+        if (reportPeriod == null) return 0;
+        String[] parts = reportPeriod.split("-");
+        if (parts.length < 2) return 0;
+        try {
+            return Integer.parseInt(parts[1]);
+        } catch (NumberFormatException e) {
+            return 0;
+        }
+    }
+
+    private double nz(Double v) {
+        return v == null ? 0.0 : v;
+    }
+}

--
Gitblit v1.9.1