| New file |
| | |
| | | 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; |
| | | |
| | | /** |
| | | * è´§è¿å£å¾è®¡ç®æå¡ï¼æ±æ»å¤§è¡¨æ°æ®é©±å¨æ¹é M1-è´§è¿ï¼2026-09-08ï¼ã |
| | | * |
| | | * å£å¾ï¼å³çåºçº¿ 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. 忝ï¼å»å¹´åå£å¾ï¼ä¸å¨æ¬æå¡è®¡ç®ï¼æ Q1 以æ¯çç¼å 2025 åç
§ç»ä¸ºåºåï¼ç±ååå±å¡«è¡¨æ¶è®¡ç®ã |
| | | * |
| | | * è¾åº key = RegionUtil è§èå¸å·åï¼æ¦æ±å¸â¦ç¥åæ¶æåºï¼+ PROVINCEï¼æ¹åçï¼å
¨çè¡ = 17 å¸å·ä¹åï¼ |
| | | * 䏿¯çâå
¨çè¡=Σåå¸è¡âå
¬å¼ä¸è´ï¼ã |
| | | */ |
| | | @Service |
| | | public class FreightCalc { |
| | | |
| | | public static final String PROVINCE = "æ¹åç"; |
| | | |
| | | /** å个æé´ï¼å½ææç´¯è®¡ï¼çè´§è¿é/å¨è½¬éä¸å£å¾ææ ï¼æ æ°æ®ä¸º 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; } |
| | | } |
| | | |
| | | /** å
¨éè´§è¿ç©éµï¼month=彿ï¼cumulative=æªè³ 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); |
| | | } |
| | | |
| | | /** åå叿æ ãcumulative=true æ¶ H2032 å 1..month å
¨æ¡¶ãå计å m01..mMM ä¹åï¼false æ¶åªå彿ã */ |
| | | 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; } |
| | | } |