From 603853a1290e7d71297c9ce5b64181a090adab87 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期二, 08 九月 2026 17:44:50 +0800
Subject: [PATCH] docs: 09-08 工作日结补记下班前状态(最新代码已重启就绪,明日待办8月填值/9月整链/临时文件清理)

---
 traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/FreightCalc.java |  225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 225 insertions(+), 0 deletions(-)

diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/FreightCalc.java b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/FreightCalc.java
new file mode 100644
index 0000000..267ccf6
--- /dev/null
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/FreightCalc.java
@@ -0,0 +1,225 @@
+package com.trafficaudit.reportexport.calc;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.trafficaudit.common.util.RegionUtil;
+import com.trafficaudit.dataimport.entity.FreightTurnoverImport;
+import com.trafficaudit.dataimport.entity.H2032EnterpriseMonthly;
+import com.trafficaudit.dataimport.entity.ScaleSplitTransport;
+import com.trafficaudit.dataimport.mapper.FreightTurnoverImportMapper;
+import com.trafficaudit.dataimport.mapper.H2032EnterpriseMonthlyMapper;
+import com.trafficaudit.dataimport.mapper.ScaleSplitTransportMapper;
+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;
+
+/**
+ * 璐ц繍鍙e緞璁$畻鏈嶅姟锛堟眹鎬诲ぇ琛ㄦ暟鎹┍鍔ㄦ敼閫� M1-璐ц繍锛�2026-09-08锛夈��
+ *
+ * 鍙e緞锛堝喅绛栧熀绾� docs/纭鍥炴墽姹囨�烩�2026-09-07.md B1锛�2026-07 涓庡凡淇姣嶇増涓ゅ紶鎴愬搧椤�
+ * 瑙勪笂/瑙勪笅 褰撴湀+绱 閫愭牸鍥炲綊 0 宸紓锛夛細
+ * 1. 瑙勪笂璐ц繍閲� = h2032_enterprise_monthly.freight_total锛堝惃锛夋寜 17 甯傚窞姹囨�� 梅10000锛堜竾鍚級銆�
+ * 2. 鍚堣璐ц繍閲� = freight_turnover_import.freight_mMM锛堝綋鏈堬級/ freight_m01..mMM锛堢疮璁★級銆�
+ * 3. 瑙勪笅璐ц繍閲� = 鍚堣 鈭� 瑙勪笂锛堟媶鍒嗚〃涓嶅瓨璐ц繍閲忓垪锛屼笉鑳界洿鎺ュ彇瑙勪笅锛夈��
+ * 4. 瑙勪笂/鍚堣鍛ㄨ浆閲� = scale_split_transport MONTH|CUMULATIVE 鐨� above_scale_turnover / total_turnover
+ *    锛堝悎璁′笌 freight_turnover_import.turnover_mMM 鍚屾簮锛屽凡鏍稿涓�鑷达級锛涜涓嬪懆杞� = 鍚堣 鈭� 瑙勪笂銆�
+ * 5. 鍚屾瘮锛堝幓骞村悓鍙e緞锛変笉鍦ㄦ湰鏈嶅姟璁$畻锛氭寜 Q1 浠ユ瘝鐗堢紦瀛� 2025 鍙傜収缁勪负鍩哄噯锛岀敱鍐欏洖灞傚~琛ㄦ椂璁$畻銆�
+ *
+ * 杈撳嚭 key = RegionUtil 瑙勮寖甯傚窞鍚嶏紙姝︽眽甯傗�︾鍐滄灦鏋楀尯锛�+ PROVINCE锛堟箹鍖楃渷锛屽叏鐪佽 = 17 甯傚窞涔嬪拰锛�
+ * 涓庢瘝鐗堚�滃叏鐪佽=危鍩庡競琛屸�濆叕寮忎竴鑷达級銆�
+ */
+@Service
+public class FreightCalc {
+
+    public static final String PROVINCE = "婀栧寳鐪�";
+
+    /** 鍗曚釜鏈熼棿锛堝綋鏈堟垨绱锛夌殑璐ц繍閲�/鍛ㄨ浆閲忎笁鍙e緞鎸囨爣锛涙棤鏁版嵁涓� null */
+    public static class FreightMetrics {
+        private final Double aboveFreight;   // 瑙勪笂璐ц繍閲忥紙涓囧惃锛�
+        private final Double belowFreight;   // 瑙勪笅璐ц繍閲忥紙涓囧惃锛�
+        private final Double totalFreight;   // 瑙勪笂+瑙勪笅璐ц繍閲忥紙涓囧惃锛�
+        private final Double aboveTurnover;  // 瑙勪笂璐х墿鍛ㄨ浆閲忥紙涓囧惃鍏噷锛�
+        private final Double belowTurnover;  // 瑙勪笅璐х墿鍛ㄨ浆閲忥紙涓囧惃鍏噷锛�
+        private final Double totalTurnover;  // 瑙勪笂+瑙勪笅璐х墿鍛ㄨ浆閲忥紙涓囧惃鍏噷锛�
+
+        public FreightMetrics(Double aboveFreight, Double belowFreight, Double totalFreight,
+                              Double aboveTurnover, Double belowTurnover, Double totalTurnover) {
+            this.aboveFreight = aboveFreight;
+            this.belowFreight = belowFreight;
+            this.totalFreight = totalFreight;
+            this.aboveTurnover = aboveTurnover;
+            this.belowTurnover = belowTurnover;
+            this.totalTurnover = totalTurnover;
+        }
+
+        public Double getAboveFreight() { return aboveFreight; }
+        public Double getBelowFreight() { return belowFreight; }
+        public Double getTotalFreight() { return totalFreight; }
+        public Double getAboveTurnover() { return aboveTurnover; }
+        public Double getBelowTurnover() { return belowTurnover; }
+        public Double getTotalTurnover() { return totalTurnover; }
+    }
+
+    /** 鍏ㄩ噺璐ц繍鐭╅樀锛歮onth=褰撴湀锛宑umulative=鎴嚦 period 鏈堢疮璁� */
+    public static class FreightMatrix {
+        private final String period;
+        private final Map<String, FreightMetrics> month;
+        private final Map<String, FreightMetrics> cumulative;
+
+        public FreightMatrix(String period, Map<String, FreightMetrics> month, Map<String, FreightMetrics> cumulative) {
+            this.period = period;
+            this.month = month;
+            this.cumulative = cumulative;
+        }
+
+        public String getPeriod() { return period; }
+        public Map<String, FreightMetrics> getMonth() { return month; }
+        public Map<String, FreightMetrics> getCumulative() { return cumulative; }
+    }
+
+    @Resource
+    private H2032EnterpriseMonthlyMapper h2032Mapper;
+    @Resource
+    private FreightTurnoverImportMapper freightTurnoverMapper;
+    @Resource
+    private ScaleSplitTransportMapper scaleSplitMapper;
+
+    /** 璁$畻 period锛堝 2026-07锛夌殑褰撴湀涓庣疮璁¤揣杩愮煩闃� */
+    public FreightMatrix calc(String period) {
+        int year = Integer.parseInt(period.substring(0, 4));
+        int month = Integer.parseInt(period.substring(5, 7));
+
+        // H2032 瑙勪笂璐ц繍閲忥紙鍚級锛氬競宸� -> 鏈堟《
+        Map<String, Map<Integer, Double>> h2032TonByCityMonth = new HashMap<>();
+        List<H2032EnterpriseMonthly> h2032List = h2032Mapper.selectList(
+            new LambdaQueryWrapper<H2032EnterpriseMonthly>().likeRight(H2032EnterpriseMonthly::getReportPeriod, year));
+        for (H2032EnterpriseMonthly rec : h2032List) {
+            String rp = rec.getReportPeriod();
+            if (rp == null || rp.compareTo(period) > 0) continue;
+            String city = RegionUtil.cityByCode(rec.getRegionCode());
+            if (city == null) continue;
+            double freight = rec.getFreightTotal() == null ? 0.0 : rec.getFreightTotal();
+            h2032TonByCityMonth.computeIfAbsent(city, k -> new HashMap<>())
+                .merge(Integer.parseInt(rp.substring(5, 7)), freight, Double::sum);
+        }
+
+        // freight_turnover_import锛氬悎璁¤揣杩愰噺/鍛ㄨ浆閲忥紙浠呭瓨鍩庡競琛岋紱婀栧寳鐪佽鐢辨眰鍜屽緱鍑猴級
+        Map<String, FreightTurnoverImport> ftMap = new HashMap<>();
+        for (FreightTurnoverImport e : freightTurnoverMapper.selectList(
+            new LambdaQueryWrapper<FreightTurnoverImport>()
+                .eq(FreightTurnoverImport::getReportPeriod, period))) {
+            String city = RegionUtil.normalizeCityName(e.getRegionName());
+            if (city != null && !PROVINCE.equals(city)) ftMap.put(city, e);
+        }
+
+        // scale_split_transport锛氳涓�/鍚堣鍛ㄨ浆閲�
+        Map<String, ScaleSplitTransport> splitMonth = new HashMap<>();
+        Map<String, ScaleSplitTransport> splitCumulative = new HashMap<>();
+        for (ScaleSplitTransport rec : scaleSplitMapper.selectList(
+            new LambdaQueryWrapper<ScaleSplitTransport>()
+                .eq(ScaleSplitTransport::getReportPeriod, period))) {
+            String city = RegionUtil.normalizeCityName(rec.getRegionName());
+            if (city == null || PROVINCE.equals(city)) continue;
+            if ("MONTH".equals(rec.getPeriodType())) splitMonth.put(city, rec);
+            else if ("CUMULATIVE".equals(rec.getPeriodType())) splitCumulative.put(city, rec);
+        }
+
+        Map<String, FreightMetrics> monthMap = new LinkedHashMap<>();
+        Map<String, FreightMetrics> cumulativeMap = new LinkedHashMap<>();
+        for (String city : RegionUtil.cityList()) {
+            monthMap.put(city, buildMetrics(city, month, h2032TonByCityMonth, ftMap, splitMonth, false));
+            cumulativeMap.put(city, buildMetrics(city, month, h2032TonByCityMonth, ftMap, splitCumulative, true));
+        }
+        monthMap.put(PROVINCE, sumOf(monthMap));
+        cumulativeMap.put(PROVINCE, sumOf(cumulativeMap));
+        return new FreightMatrix(period, monthMap, cumulativeMap);
+    }
+
+    /** 鍗曞煄甯傛寚鏍囥�俢umulative=true 鏃� H2032 鍙� 1..month 鍏ㄦ《銆佸悎璁″彇 m01..mMM 涔嬪拰锛沠alse 鏃跺彧鍙栧綋鏈堛�� */
+    private FreightMetrics buildMetrics(String city, int month,
+                                        Map<String, Map<Integer, Double>> h2032TonByCityMonth,
+                                        Map<String, FreightTurnoverImport> ftMap,
+                                        Map<String, ScaleSplitTransport> splitMap,
+                                        boolean cumulative) {
+        Double aboveFreight = null;
+        Map<Integer, Double> h2032Buckets = h2032TonByCityMonth.get(city);
+        if (h2032Buckets != null) {
+            double ton;
+            if (cumulative) {
+                ton = 0.0;
+                for (int m = 1; m <= month; m++) ton += h2032Buckets.getOrDefault(m, 0.0);
+            } else {
+                ton = h2032Buckets.getOrDefault(month, 0.0);
+            }
+            aboveFreight = ton / 10000.0;
+        }
+
+        FreightTurnoverImport ft = ftMap.get(city);
+        Double totalFreight = null;
+        Double totalTurnoverFromFt = null;
+        if (ft != null) {
+            if (cumulative) {
+                double f = 0.0, t = 0.0;
+                for (int m = 1; m <= month; m++) {
+                    f += monthField(ft, m, true);
+                    t += monthField(ft, m, false);
+                }
+                totalFreight = f;
+                totalTurnoverFromFt = t;
+            } else {
+                totalFreight = monthField(ft, month, true);
+                totalTurnoverFromFt = monthField(ft, month, false);
+            }
+        }
+
+        ScaleSplitTransport split = splitMap.get(city);
+        Double aboveTurnover = split == null ? null : split.getAboveScaleTurnover();
+        Double totalTurnover = split != null && split.getTotalTurnover() != null
+            ? split.getTotalTurnover() : totalTurnoverFromFt;
+
+        Double belowFreight = totalFreight == null || aboveFreight == null ? null : totalFreight - aboveFreight;
+        Double belowTurnover = totalTurnover == null ? null
+            : totalTurnover - (aboveTurnover == null ? 0.0 : aboveTurnover);
+        return new FreightMetrics(aboveFreight, belowFreight, totalFreight,
+                                  aboveTurnover, belowTurnover, totalTurnover);
+    }
+
+    /** 婀栧寳鐪佽 = 17 甯傚窞涔嬪拰锛堜笌姣嶇増鍏ㄧ渷琛� 危 鍏紡涓�鑷达紱鍏ㄥ競宸炴棤鏁版嵁鏃惰緭鍑� 0锛� */
+    private FreightMetrics sumOf(Map<String, FreightMetrics> byCity) {
+        double af = 0.0, bf = 0.0, tf = 0.0, at = 0.0, bt = 0.0, tt = 0.0;
+        for (String city : RegionUtil.cityList()) {
+            FreightMetrics m = byCity.get(city);
+            if (m == null) continue;
+            af += nz(m.getAboveFreight());
+            bf += nz(m.getBelowFreight());
+            tf += nz(m.getTotalFreight());
+            at += nz(m.getAboveTurnover());
+            bt += nz(m.getBelowTurnover());
+            tt += nz(m.getTotalTurnover());
+        }
+        return new FreightMetrics(af, bf, tf, at, bt, tt);
+    }
+
+    private double monthField(FreightTurnoverImport e, int m, boolean freight) {
+        switch (m) {
+            case 1: return freight ? nz(e.getFreightM01()) : nz(e.getTurnoverM01());
+            case 2: return freight ? nz(e.getFreightM02()) : nz(e.getTurnoverM02());
+            case 3: return freight ? nz(e.getFreightM03()) : nz(e.getTurnoverM03());
+            case 4: return freight ? nz(e.getFreightM04()) : nz(e.getTurnoverM04());
+            case 5: return freight ? nz(e.getFreightM05()) : nz(e.getTurnoverM05());
+            case 6: return freight ? nz(e.getFreightM06()) : nz(e.getTurnoverM06());
+            case 7: return freight ? nz(e.getFreightM07()) : nz(e.getTurnoverM07());
+            case 8: return freight ? nz(e.getFreightM08()) : nz(e.getTurnoverM08());
+            case 9: return freight ? nz(e.getFreightM09()) : nz(e.getTurnoverM09());
+            case 10: return freight ? nz(e.getFreightM10()) : nz(e.getTurnoverM10());
+            case 11: return freight ? nz(e.getFreightM11()) : nz(e.getTurnoverM11());
+            case 12: return freight ? nz(e.getFreightM12()) : nz(e.getTurnoverM12());
+            default: return 0.0;
+        }
+    }
+
+    private double nz(Double v) { return v == null ? 0.0 : v; }
+}

--
Gitblit v1.9.1