Browse Source

feat: 存储过程开发

weijianghai 11 months ago
parent
commit
995cce2cad
46 changed files with 9342 additions and 29 deletions
  1. 28 28
      readme.md
  2. 1 1
      src/main/java/com/nokia/finance/tasks/config/web/RequestLogHandlerInterceptor.java
  3. 953 0
      src/main/java/com/nokia/finance/tasks/dao/car/CarCxdpDao.java
  4. 22 0
      src/main/java/com/nokia/finance/tasks/dao/car/CarGongCheShouFeiDao.java
  5. 1931 0
      src/main/java/com/nokia/finance/tasks/dao/car/CarProcedureDao.java
  6. 1105 0
      src/main/java/com/nokia/finance/tasks/dao/car/CarStrategyDao.java
  7. 603 0
      src/main/java/com/nokia/finance/tasks/dao/gdc/car/GdcCarProcedureDao.java
  8. 104 0
      src/main/java/com/nokia/finance/tasks/dao/gdc/house/GdcHouseProcedureDao.java
  9. 231 0
      src/main/java/com/nokia/finance/tasks/dao/house/HouseFcdpDao.java
  10. 316 0
      src/main/java/com/nokia/finance/tasks/dao/house/HouseStrategyDao.java
  11. 81 0
      src/main/java/com/nokia/finance/tasks/jobs/car/cxdp/CarCxdpJob.java
  12. 51 0
      src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarBaseDataMonthProcJob.java
  13. 71 0
      src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarFeeProcJob.java
  14. 57 0
      src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarLiChengMonthProcJob.java
  15. 59 0
      src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarPaiDanProcJob.java
  16. 398 0
      src/main/java/com/nokia/finance/tasks/jobs/car/ruixing/CarYongCheZongLanJob.java
  17. 80 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarHighFuelConsumptionJob.java
  18. 79 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarHighRepairJob.java
  19. 79 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarInefficiencyPercentJob.java
  20. 79 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarInefficiencyQxJob.java
  21. 81 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarRentalRepairJob.java
  22. 80 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarViolationUnprocessedJob.java
  23. 76 0
      src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarWdyjJob.java
  24. 79 0
      src/main/java/com/nokia/finance/tasks/jobs/house/fcdp/HouseBuildingAreaStatJob.java
  25. 78 0
      src/main/java/com/nokia/finance/tasks/jobs/house/fcdp/HouseBuildingLandCountJob.java
  26. 69 0
      src/main/java/com/nokia/finance/tasks/jobs/house/fcdp/HouseRentalIncomeJob.java
  27. 55 0
      src/main/java/com/nokia/finance/tasks/jobs/house/procedure/HouseBuildingRepairProcJob.java
  28. 81 0
      src/main/java/com/nokia/finance/tasks/jobs/house/strategy/HouseBuildingIdleStrategyJob.java
  29. 16 0
      src/main/java/com/nokia/finance/tasks/service/car/CarService.java
  30. 44 0
      src/main/java/com/nokia/finance/tasks/utils/PinYinUtil.java
  31. 42 0
      src/test/java/com/nokia/finance/tasks/HanZiToPinYinTest.java
  32. 329 0
      src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests.java
  33. 329 0
      src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests1.java
  34. 438 0
      src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests2.java
  35. 373 0
      src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests3.java
  36. 203 0
      src/test/java/com/nokia/finance/tasks/car/CarJiaoTongBuTieTests.java
  37. 407 0
      src/test/java/com/nokia/finance/tasks/car/CarLianXuJiaYouTests.java
  38. 50 0
      src/test/java/com/nokia/finance/tasks/car/CarStrategyJobTests.java
  39. 22 0
      src/test/java/com/nokia/finance/tasks/car/procedure/CarBaseDataMonthProcJobTests.java
  40. 22 0
      src/test/java/com/nokia/finance/tasks/car/procedure/CarFeeProcJobTests.java
  41. 22 0
      src/test/java/com/nokia/finance/tasks/car/procedure/CarLiChengMonthProcJobTests.java
  42. 22 0
      src/test/java/com/nokia/finance/tasks/car/procedure/CarPaiDanProcJobTests.java
  43. 22 0
      src/test/java/com/nokia/finance/tasks/car/ruixing/CarYongCheZongLanJobTests.java
  44. 30 0
      src/test/java/com/nokia/finance/tasks/house/fcdp/HouseFcdpJobTests.java
  45. 22 0
      src/test/java/com/nokia/finance/tasks/house/procedure/HouseBuildingRepairProcJobTests.java
  46. 22 0
      src/test/java/com/nokia/finance/tasks/house/strategy/HouseBuildingIdleStrategyJobTests.java

+ 28 - 28
readme.md

@@ -13,7 +13,7 @@
 ##### 睿行车辆基本信息日数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_BASE_DATA_DAY_JOB"
@@ -23,7 +23,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 睿行车辆越界报警日数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_YUE_JIE_JOB"
@@ -33,7 +33,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 睿行车辆报废月数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_BAO_FEI_JOB"
@@ -43,7 +43,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 睿行车辆行驶里程月数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_LI_CHENG_MONTH_JOB"
@@ -53,7 +53,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 睿行车辆无单用车报警月统计数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_WU_DAN_YONG_CHE_JOB"
@@ -63,19 +63,29 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 睿行车辆用车月统计数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_YONG_CHE_JOB"
 }'
 ```
 
+##### 睿行车辆行驶里程日数据入库定时任务
+
+```shell
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
+--header 'Content-Type: application/json' \
+--data '{
+    "jobName": "CAR_LI_CHENG_DAY_JOB"
+}'
+```
+
 #### 成本系统
 
 ##### 河北成本管理系统车辆燃油数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_RAN_YOU_JOB"
@@ -85,7 +95,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆大额维修数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_DA_WEI_XIU_JOB"
@@ -95,7 +105,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆普通维修数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_WEI_XIU_JOB"
@@ -105,7 +115,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆路桥数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_LU_QIAO_JOB"
@@ -115,7 +125,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆保险数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_BAO_XIAN_JOB"
@@ -125,7 +135,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆年检数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_NIAN_JIAN_FEI_JOB"
@@ -135,7 +145,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆其他费用数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_QI_TA_JOB"
@@ -145,7 +155,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北价值管理平台省内车辆费用月数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_FEE_HB_JOB"
@@ -155,7 +165,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北价值管理平台北十车辆费用月数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_FEE_BS_JOB"
@@ -165,7 +175,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统自有类房产维修数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "HOUSE_BUILDING_REPAIR_MONTH_JOB"
@@ -175,17 +185,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统车辆私车公用数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
---header 'Content-Type: application/json' \
---data '{
-    "jobName": "CAR_SI_CHE_GONG_YONG_JOB"
-}'
-```
-
-##### 河北成本管理系统车辆私车公用数据入库定时任务
-
-```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "CAR_SI_CHE_GONG_YONG_JOB"
@@ -195,7 +195,7 @@ curl --location 'http://localhost:39110/jobs/runJob' \
 ##### 河北成本管理系统不动产租赁房产维修数据入库定时任务
 
 ```shell
-curl --location 'http://localhost:39110/jobs/runJob' \
+curl --location 'http://127.0.0.1:39110/jobs/runJob' \
 --header 'Content-Type: application/json' \
 --data '{
     "jobName": "HOUSE_RENT_IN_REPAIR_MONTH_JOB"

+ 1 - 1
src/main/java/com/nokia/finance/tasks/config/web/RequestLogHandlerInterceptor.java

@@ -59,7 +59,7 @@ public class RequestLogHandlerInterceptor implements HandlerInterceptor {
         log.info("请求体参数: {}", StringUtils.trimAllWhitespace(body));
         String remoteAddr = request.getRemoteAddr();
         // 判断请求是否来自本地
-        if (!("localhost".equals(remoteAddr) || "127.0.0.1".equals(remoteAddr))) {
+        if (!"127.0.0.1".equals(remoteAddr)) {
             log.warn("非本地请求: {}", remoteAddr);
             return false;
         }

+ 953 - 0
src/main/java/com/nokia/finance/tasks/dao/car/CarCxdpDao.java

@@ -0,0 +1,953 @@
+package com.nokia.finance.tasks.dao.car;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+@Mapper
+public interface CarCxdpDao {
+    /**
+     * 判断是否有车效大屏需要的数据
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+    (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_base_data_month
+        where
+            year_month = #{endYearMonth}))
+    and (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_fei_yong_month
+        where
+            year_month = #{endYearMonth}))
+    and (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_li_cheng_month
+        where
+            year_month = #{endYearMonth}))
+    and (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_wei_zhang
+        where
+            year_month = #{endYearMonth}))
+""")
+    boolean hasCarCxdp(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车效大屏建设数据
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+a101 as (
+select
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+),
+a102 as (
+select
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+),
+a103 as (
+select
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and che_liang_lai_yuan = '租赁车辆'
+),
+a104 as (
+select
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+),
+a105 as (
+select
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+),
+a106 as (
+select
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+),
+a107 as (
+select
+count(1) as wei_gui_count
+from car.car_wei_gui
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+),
+a111 as (
+select
+'018' as area_no,
+'河北省' as area_name,
+'' as city_no,
+'' as city_name,
+a101.total,
+a101.zi_you_count,
+a101.zu_lin_count,
+a101.qiang_xiu_count,
+a101.zong_he_sheng_chan_count,
+a101.yi_ban_gong_wu_count,
+a101.te_zong_che_count,
+a101.fu_ze_ren_count,
+a102.ran_you_sum as zong_you_hao,
+a104.li_cheng_sum,
+case when a104.li_cheng_sum = 0 then null else a102.ran_you_sum / a104.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+a102.wei_xiu_sum,
+case when a101.zi_you_count = 0 then null else a102.wei_xiu_sum / a101.zi_you_count end as wei_xiu_month_avg,
+a107.wei_gui_count,
+a105.di_xiao_count,
+a106.wei_zhang_count,
+a103.zu_lin_wei_xiu,
+0 as shu_ju_lei_xing,
+'A' as shu_ju_da_lei
+from a101
+cross join a102
+cross join a103
+cross join a104
+cross join a105
+cross join a106
+cross join a107
+),
+a201 as (
+select
+area_no,
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+group by area_no
+),
+a202 as (
+select
+area_no,
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+group by area_no
+),
+a203 as (
+select
+area_no,
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and che_liang_lai_yuan = '租赁车辆'
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+group by area_no
+),
+a204 as (
+select
+area_no,
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+group by area_no
+),
+a205 as (
+select
+area_no,
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+group by area_no
+),
+a206 as (
+select
+area_no,
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+group by area_no
+),
+a207 as (
+select
+area_no,
+count(1) as wei_gui_count
+from car.car_wei_gui
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+group by area_no
+),
+a211 as (
+select
+a201.area_no,
+o1.name as area_name,
+'' as city_no,
+'' as city_name,
+a201.total,
+a201.zi_you_count,
+a201.zu_lin_count,
+a201.qiang_xiu_count,
+a201.zong_he_sheng_chan_count,
+a201.yi_ban_gong_wu_count,
+a201.te_zong_che_count,
+a201.fu_ze_ren_count,
+a202.ran_you_sum as zong_you_hao,
+a204.li_cheng_sum,
+case when a204.li_cheng_sum = 0 then null else a202.ran_you_sum / a204.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+a202.wei_xiu_sum,
+case when a201.zi_you_count = 0 then null else a202.wei_xiu_sum / a201.zi_you_count end as wei_xiu_month_avg,
+a207.wei_gui_count,
+a205.di_xiao_count,
+a206.wei_zhang_count,
+a203.zu_lin_wei_xiu,
+1 as shu_ju_lei_xing,
+'A' as shu_ju_da_lei
+from a201 
+left join common.organization o1 on a201.area_no = o1.id
+left join a202 on a201.area_no = a202.area_no
+left join a203 on a201.area_no = a203.area_no
+left join a204 on a201.area_no = a204.area_no
+left join a205 on a201.area_no = a205.area_no
+left join a206 on a201.area_no = a206.area_no
+left join a207 on a201.area_no = a207.area_no
+),
+a301 as (
+select
+area_no,
+city_no,
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month 
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+group by area_no, city_no
+),
+a302 as (
+select
+area_no,
+city_no,
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+group by area_no, city_no
+),
+a303 as (
+select
+area_no,
+city_no,
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and che_liang_lai_yuan = '租赁车辆'
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+group by area_no, city_no
+),
+a304 as (
+select
+area_no,
+city_no,
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month 
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+group by area_no, city_no
+),
+a305 as (
+select
+area_no,
+city_no,
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+group by area_no, city_no
+),
+a306 as (
+select
+area_no,
+city_no,
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+group by area_no, city_no
+),
+a307 as (
+select
+area_no,
+city_no,
+count(1) as wei_gui_count
+from car.car_wei_gui 
+where year_month = #{endYearMonth}
+and area_name != '省机动局'
+and area_name != '省本部'
+and area_no is not null
+and area_no != ''
+and city_no is not null
+and city_no != ''
+group by area_no, city_no
+),
+a311 as (
+select
+a301.area_no,
+o1.name as area_name,
+a301.city_no,
+o2.name as city_name,
+a301.total,
+a301.zi_you_count,
+a301.zu_lin_count,
+a301.qiang_xiu_count,
+a301.zong_he_sheng_chan_count,
+a301.yi_ban_gong_wu_count,
+a301.te_zong_che_count,
+a301.fu_ze_ren_count,
+a302.ran_you_sum as zong_you_hao,
+a304.li_cheng_sum,
+case when a304.li_cheng_sum = 0 then null else a302.ran_you_sum / a304.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+a302.wei_xiu_sum,
+case when a301.zi_you_count = 0 then null else a302.wei_xiu_sum / a301.zi_you_count end as wei_xiu_month_avg,
+a307.wei_gui_count,
+a305.di_xiao_count,
+a306.wei_zhang_count,
+a303.zu_lin_wei_xiu,
+2 as shu_ju_lei_xing,
+'A' as shu_ju_da_lei
+from a301 
+left join common.organization o1 on a301.area_no = o1.id
+left join common.organization o2 on a301.city_no = o2.id
+left join a302 on a301.area_no = a302.area_no and a301.city_no = a302.city_no
+left join a303 on a301.area_no = a303.area_no and a301.city_no = a303.city_no
+left join a304 on a301.area_no = a304.area_no and a301.city_no = a304.city_no
+left join a305 on a301.area_no = a305.area_no and a301.city_no = a305.city_no
+left join a306 on a301.area_no = a306.area_no and a301.city_no = a306.city_no
+left join a307 on a301.area_no = a307.area_no and a301.city_no = a307.city_no
+),
+b101 as (
+select
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month 
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+),
+b102 as (
+select
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name = '省机动局'
+),
+b103 as (
+select
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+and che_liang_lai_yuan = '租赁车辆'
+),
+b104 as (
+select
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month 
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name = '省机动局'
+),
+b105 as (
+select
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name = '省机动局'
+),
+b106 as (
+select
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+),
+b107 as (
+select
+count(1) as wei_gui_count
+from car.car_wei_gui 
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+),
+b111 as (
+select
+'018' as area_no,
+'河北省' as area_name,
+'' as city_no,
+'' as city_name,
+b101.total,
+b101.zi_you_count,
+b101.zu_lin_count,
+b101.qiang_xiu_count,
+b101.zong_he_sheng_chan_count,
+b101.yi_ban_gong_wu_count,
+b101.te_zong_che_count,
+b101.fu_ze_ren_count,
+b102.ran_you_sum as zong_you_hao,
+b104.li_cheng_sum,
+case when b104.li_cheng_sum = 0 then null else b102.ran_you_sum / b104.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+b102.wei_xiu_sum,
+case when b101.zi_you_count = 0 then null else b102.wei_xiu_sum / b101.zi_you_count end as wei_xiu_month_avg,
+b107.wei_gui_count,
+b105.di_xiao_count,
+b106.wei_zhang_count,
+b103.zu_lin_wei_xiu,
+0 as shu_ju_lei_xing,
+'B' as shu_ju_da_lei
+from b101 
+cross join b102
+cross join b103
+cross join b104
+cross join b105
+cross join b106
+cross join b107
+),
+b201 as (
+select
+area_no2 as area_no,
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month 
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+group by area_no2
+),
+b202 as (
+select
+area_no2 as area_no,
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+b203 as (
+select
+area_no2 as area_no,
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and che_liang_lai_yuan = '租赁车辆'
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+b204 as (
+select
+area_no2 as area_no,
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month 
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+b205 as (
+select
+area_no2 as area_no,
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+b206 as (
+select
+area_no2 as area_no,
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+b207 as (
+select
+area_no2 as area_no,
+count(1) as wei_gui_count
+from car.car_wei_gui 
+where year_month = #{endYearMonth}
+and area_name = '省机动局'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+b211 as (
+select
+b201.area_no,
+o1.name as area_name,
+'' as city_no,
+'' as city_name,
+b201.total,
+b201.zi_you_count,
+b201.zu_lin_count,
+b201.qiang_xiu_count,
+b201.zong_he_sheng_chan_count,
+b201.yi_ban_gong_wu_count,
+b201.te_zong_che_count,
+b201.fu_ze_ren_count,
+b202.ran_you_sum as zong_you_hao,
+b204.li_cheng_sum,
+case when b204.li_cheng_sum = 0 then null else b202.ran_you_sum / b204.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+b202.wei_xiu_sum,
+case when b201.zi_you_count = 0 then null else b202.wei_xiu_sum / b201.zi_you_count end as wei_xiu_month_avg,
+b207.wei_gui_count,
+b205.di_xiao_count,
+b206.wei_zhang_count,
+b203.zu_lin_wei_xiu,
+1 as shu_ju_lei_xing,
+'B' as shu_ju_da_lei
+from b201 
+left join common.organization o1 on b201.area_no = o1.id
+left join b202 on b201.area_no = b202.area_no
+left join b203 on b201.area_no = b203.area_no
+left join b204 on b201.area_no = b204.area_no
+left join b205 on b201.area_no = b205.area_no
+left join b206 on b201.area_no = b206.area_no
+left join b207 on b201.area_no = b207.area_no
+),
+c101 as (
+select
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month
+where year_month = #{endYearMonth}
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+),
+c102 as (
+select
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+),
+c103 as (
+select
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and che_liang_lai_yuan = '租赁车辆'
+),
+c104 as (
+select
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month 
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+),
+c105 as (
+select
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+),
+c106 as (
+select
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+),
+c107 as (
+select
+count(1) as wei_gui_count
+from car.car_wei_gui 
+where year_month = #{endYearMonth}
+),
+c111 as (
+select
+'018' as area_no,
+'河北省' as area_name,
+'' as city_no,
+'' as city_name,
+c101.total,
+c101.zi_you_count,
+c101.zu_lin_count,
+c101.qiang_xiu_count,
+c101.zong_he_sheng_chan_count,
+c101.yi_ban_gong_wu_count,
+c101.te_zong_che_count,
+c101.fu_ze_ren_count,
+c102.ran_you_sum as zong_you_hao,
+c104.li_cheng_sum,
+case when c104.li_cheng_sum = 0 then null else c102.ran_you_sum / c104.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+c102.wei_xiu_sum,
+case when c101.zi_you_count = 0 then null else c102.wei_xiu_sum / c101.zi_you_count end as wei_xiu_month_avg,
+c107.wei_gui_count,
+c105.di_xiao_count,
+c106.wei_zhang_count,
+c103.zu_lin_wei_xiu,
+0 as shu_ju_lei_xing,
+'C' as shu_ju_da_lei
+from c101 
+cross join c102
+cross join c103
+cross join c104
+cross join c105
+cross join c106
+cross join c107
+),
+c201 as (
+select
+area_no2 as area_no,
+count(1) as total,
+count(che_liang_lai_yuan = '自有车辆' or null) as zi_you_count,
+count(che_liang_lai_yuan = '租赁车辆' or null) as zu_lin_count,
+count(che_liang_shi_yong_xing_zhi = '抢修用车' or null) as qiang_xiu_count,
+count(che_liang_shi_yong_xing_zhi = '综合生产用车' or null) as zong_he_sheng_chan_count,
+count(che_liang_shi_yong_xing_zhi = '一般公务用车' or null) as yi_ban_gong_wu_count,
+count(che_liang_shi_yong_xing_zhi = '特种车' or null) as te_zong_che_count,
+count(che_liang_shi_yong_xing_zhi = '负责人用车' or null) as fu_ze_ren_count
+from car.car_base_data_month 
+where year_month = #{endYearMonth}
+and area_no2 is not null
+and area_no2 != ''
+and che_liang_lai_yuan in ('自有车辆', '租赁车辆')
+and che_liang_shi_yong_xing_zhi in ('抢修用车', '综合生产用车', '一般公务用车', '特种车', '负责人用车')
+group by area_no2
+),
+c202 as (
+select
+area_no2 as area_no,
+sum(ran_you) as ran_you_sum,
+sum(wei_xiu) as wei_xiu_sum
+from car.car_fei_yong_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+c203 as (
+select
+area_no2 as area_no,
+sum(wei_xiu) as zu_lin_wei_xiu
+from car.car_fei_yong_month
+where year_month = #{endYearMonth}
+and che_liang_lai_yuan = '租赁车辆'
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+c204 as (
+select
+area_no2 as area_no,
+sum(zong_li_cheng) as li_cheng_sum
+from car.car_li_cheng_month 
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+c205 as (
+select
+area_no2 as area_no,
+count(1) as di_xiao_count
+from car.car_di_xiao_month
+where year_month >= #{startYearMonth}
+and year_month <= #{endYearMonth}
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+c206 as (
+select
+area_no2 as area_no,
+count(1) as wei_zhang_count
+from car.car_wei_zhang_chang_qi
+where year_month = #{endYearMonth}
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+c207 as (
+select
+area_no2 as area_no,
+count(1) as wei_gui_count
+from car.car_wei_gui 
+where year_month = #{endYearMonth}
+and area_no2 is not null
+and area_no2 != ''
+group by area_no2
+),
+c211 as (
+select
+c201.area_no,
+o1.name as area_name,
+'' as city_no,
+'' as city_name,
+c201.total,
+c201.zi_you_count,
+c201.zu_lin_count,
+c201.qiang_xiu_count,
+c201.zong_he_sheng_chan_count,
+c201.yi_ban_gong_wu_count,
+c201.te_zong_che_count,
+c201.fu_ze_ren_count,
+c202.ran_you_sum as zong_you_hao,
+c204.li_cheng_sum,
+case when c204.li_cheng_sum = 0 then null else c202.ran_you_sum / c204.li_cheng_sum * 100 end as bai_gong_li_you_hao,
+c202.wei_xiu_sum,
+case when c201.zi_you_count = 0 then null else c202.wei_xiu_sum / c201.zi_you_count end as wei_xiu_month_avg,
+c207.wei_gui_count,
+c205.di_xiao_count,
+c206.wei_zhang_count,
+c203.zu_lin_wei_xiu,
+1 as shu_ju_lei_xing,
+'C' as shu_ju_da_lei
+from c201 
+left join common.organization o1 on c201.area_no = o1.id
+left join c202 on c201.area_no = c202.area_no
+left join c203 on c201.area_no = c203.area_no
+left join c204 on c201.area_no = c204.area_no
+left join c205 on c201.area_no = c205.area_no
+left join c206 on c201.area_no = c206.area_no
+left join c207 on c201.area_no = c207.area_no
+),
+d111 as (
+select * from a111
+union all
+select * from a211
+union all
+select * from a311
+union all
+select * from b111
+union all
+select * from b211
+union all
+select * from c111
+union all
+select * from c211
+)
+insert into publish.car_cxdp
+(
+acct_date,
+area_no,
+area_name,
+city_no,
+city_name,
+zi_you_count,
+zu_lin_count,
+qiang_xiu_count,
+zong_he_sheng_chan_count,
+yi_ban_gong_wu_count,
+te_zong_che_count,
+fu_ze_ren_count,
+zong_you_hao,
+li_cheng_sum,
+bai_gong_li_you_hao,
+wei_xiu_sum,
+wei_xiu_month_avg,
+wei_gui_count,
+di_xiao_count,
+wei_zhang_count,
+zu_lin_wei_xiu,
+shu_ju_lei_xing,
+shu_ju_da_lei
+)
+select
+#{endYearMonth} as acct_date,
+area_no,
+area_name,
+city_no,
+city_name,
+zi_you_count,
+zu_lin_count,
+qiang_xiu_count,
+zong_he_sheng_chan_count,
+yi_ban_gong_wu_count,
+te_zong_che_count,
+fu_ze_ren_count,
+round(coalesce(zong_you_hao, 0), 2) as zong_you_hao,
+round(coalesce(li_cheng_sum, 0), 2) as li_cheng_sum,
+round(bai_gong_li_you_hao, 2) as bai_gong_li_you_hao,
+round(coalesce(wei_xiu_sum, 0), 2) as wei_xiu_sum,
+round(wei_xiu_month_avg, 2) as wei_xiu_month_avg,
+coalesce(wei_gui_count, 0) as wei_gui_count,
+coalesce(di_xiao_count, 0) as di_xiao_count,
+coalesce(wei_zhang_count, 0) as wei_zhang_count,
+round(coalesce(zu_lin_wei_xiu, 0), 2) as zu_lin_wei_xiu,
+shu_ju_lei_xing,
+shu_ju_da_lei
+from d111
+""")
+    int insertCarCxdp(@Param("startYearMonth") Integer startYearMonth, @Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询车效大屏建设数据
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select * from publish.car_cxdp where acct_date = #{endYearMonth}
+""")
+    List<LinkedHashMap<String, Object>> getCarCxdp(@Param("endYearMonth") Integer endYearMonth);
+}

+ 22 - 0
src/main/java/com/nokia/finance/tasks/dao/car/CarGongCheShouFeiDao.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.dao.car;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Mapper
+public interface CarGongCheShouFeiDao {
+    @Select("""
+select distinct xing_ming, first_unit from car.car_jiao_tong_bu_tie_month where year_month >= #{yearMonth}
+""")
+    List<Map<String, String>> getStaffs(@Param("yearMonth") Integer yearMonth);
+
+    @Select("""
+select distinct card_num from car_theme.wz_f_spc_car where is_spec = '1'
+""")
+    Set<String> getSpecialCar();
+}

+ 1931 - 0
src/main/java/com/nokia/finance/tasks/dao/car/CarProcedureDao.java

@@ -0,0 +1,1931 @@
+package com.nokia.finance.tasks.dao.car;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+@Mapper
+public interface CarProcedureDao {
+    /**
+     * 插入车辆基本信息月数据
+     *
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car.car_base_data_month
+(
+year_month,
+che_pai_hao,
+che_liang_pin_pai,
+pai_liang,
+pai_liang_lei_xing,
+ran_you_lei_xing,
+ran_you_biao_hao,
+deng_ji_ri_qi,
+che_liang_lai_yuan,
+che_liang_lei_xing,
+che_liang_shi_yong_xing_zhi,
+huan_bao_deng_ji,
+fa_dong_ji_hao,
+che_jia_hao,
+chu_shi_li_cheng,
+che_liang_suo_shu_dan_wei,
+xing_shi_zheng_hao,
+bei_zhu,
+shen_he_zhuang_tai,
+che_liang_zhuang_tai,
+zi_chan_bian_hao,
+bang_ding_jia_shi_yuan_xing_ming,
+gou_zhi_jia_ge,
+che_ling_nian,
+biao_zhun_bai_gong_li_you_hao,
+she_bei_gong_zuo_mo_shi,
+yong_che_mo_shi,
+first_unit,
+second_unit,
+third_unit,
+area_no,
+area_name,
+city_no,
+city_name,
+area_no2,
+area_name2,
+city_id,
+city,
+district_id,
+district,
+data_date,
+last_month,
+year_no,
+month_no,
+raw_che_pai_hao,
+che_pai_fail,
+che_ling,
+source
+)
+select
+year_month,
+che_pai_hao,
+che_liang_pin_pai,
+pai_liang,
+pai_liang_lei_xing,
+ran_you_lei_xing,
+ran_you_biao_hao,
+deng_ji_ri_qi,
+che_liang_lai_yuan,
+che_liang_lei_xing,
+che_liang_shi_yong_xing_zhi,
+huan_bao_deng_ji,
+fa_dong_ji_hao,
+che_jia_hao,
+chu_shi_li_cheng,
+che_liang_suo_shu_dan_wei,
+xing_shi_zheng_hao,
+bei_zhu,
+shen_he_zhuang_tai,
+che_liang_zhuang_tai,
+zi_chan_bian_hao,
+bang_ding_jia_shi_yuan_xing_ming,
+gou_zhi_jia_ge,
+che_ling_nian,
+biao_zhun_bai_gong_li_you_hao,
+she_bei_gong_zuo_mo_shi,
+yong_che_mo_shi,
+first_unit,
+second_unit,
+third_unit,
+area_no,
+area_name,
+city_no,
+city_name,
+area_no2,
+area_name2,
+city_id,
+city,
+district_id,
+district,
+data_date,
+last_month,
+year_no,
+month_no,
+raw_che_pai_hao,
+che_pai_fail,
+che_ling,
+source
+from car.car_base_data_day
+where data_date = (select max(data_date) from car.car_base_data_day where year_month = #{endYearMonth})
+""")
+    int insertCarBaseDataMonth(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆基本信息月数据新车调配字段
+     *
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update
+    car.car_base_data_month a
+set
+    car_new = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+            )) then 0
+        else 1
+    end,
+    car_new_year_month = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+            )) then (
+            select
+                car_new_year_month
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+            )
+        else year_month
+    end,
+    car_new_date = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+            )) then (
+            select
+                car_new_date
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+            )
+        else to_date(year_month::varchar, 'YYYYMM')
+    end,
+    car_move = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.che_liang_suo_shu_dan_wei != b.che_liang_suo_shu_dan_wei
+            )) then 1
+        else 0
+    end,
+    car_move_yj = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.first_unit != b.first_unit
+            )) then 1
+        else 0
+    end,
+    car_move_yj_year_month = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.first_unit != b.first_unit
+            )) then year_month
+        else (
+            select
+                car_move_yj_year_month
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+        )
+    end,
+    car_move_yj_date = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.first_unit != b.first_unit
+            )) then to_date(year_month::varchar, 'YYYYMM')
+        else (
+            select
+                car_move_yj_date
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+        )
+    end,
+    last_first_unit = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.first_unit != b.first_unit
+            )) then (
+            select
+                first_unit
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+            )
+        else (
+            select
+                last_first_unit
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+        )
+    end,
+    car_move_ej = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.second_unit != b.second_unit
+            )) then 1
+        else 0
+    end,
+    car_move_sj = case
+        when (
+        select
+            exists(
+            select
+                1
+            from
+                car.car_base_data_month b
+            where
+                a.last_month = b.year_month
+                and a.che_pai_hao = b.che_pai_hao
+                and a.third_unit != b.third_unit
+            )) then 1
+        else 0
+    end
+where year_month = #{endYearMonth}
+""")
+    int updateCarBaseDataMonthChange(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆行驶里程月数据工作日
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update
+    car.car_li_cheng_month a
+set
+    workday = b.workday
+from
+    car.workdays b
+where
+    a.year_month = b.year_month
+    and a.year_month = #{endYearMonth}
+""")
+    int updateCarLiChengMonthWorkday(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆行驶里程月数据日均里程出勤率
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update
+    car.car_li_cheng_month
+set
+    ri_jun_li_cheng = zong_li_cheng / workday,
+    chu_qin_lv = xing_shi_tian_shu / workday::numeric
+where
+    year_month = #{endYearMonth}
+""")
+    int updateCarLiChengMonthRiJunLiChengChuQinLv(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆行驶里程月数据低效
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update
+    car.car_li_cheng_month a
+set
+    di_xiao = case
+        when first_unit = '省公司本部' then 0
+        when position('建设部' in che_liang_suo_shu_dan_wei) > 0 then 0
+        when che_liang_lei_xing in ('特种车', '中型面包车(8-20座的面包车)', '大巴车') then 0
+        when che_liang_shi_yong_xing_zhi in ('特种车', '负责人用车') then 0
+        when (select exists(select 1 from car_theme.wz_f_spc_car b where a.che_pai_hao = b.card_num and b.is_spec = '1')) then 0
+        when (select exists(select 1 from car.car_bao_fei b where b.che_pai_hao = a.che_pai_hao and b.year_month <= #{endYearMonth})) then 0
+        when bao_fei = 1 then 0
+        when chu_qin_lv < 0.5 and ri_jun_li_cheng < 20 then 1
+        else 0
+    end,
+    di_xiao_exclude_reason = case
+        when (select exists(select 1 from car.car_bao_fei b where b.che_pai_hao = a.che_pai_hao and b.year_month <= #{endYearMonth})) then (select max(b.year_month) from car.car_bao_fei b where b.che_pai_hao = a.che_pai_hao and b.year_month <= #{endYearMonth}) || '报废'
+        when first_unit = '省公司本部' then '省公司本部'
+        when position('建设部' in che_liang_suo_shu_dan_wei) > 0 then '建设部'
+        when che_liang_lei_xing = '特种车' then '特种车'
+        when che_liang_lei_xing = '中型面包车(8-20座的面包车)' then '中型面包车(8-20座的面包车)'
+        when che_liang_lei_xing = '大巴车' then '大巴车'
+        when che_liang_shi_yong_xing_zhi = '特种车' then '特种车'
+        when che_liang_shi_yong_xing_zhi = '负责人用车' then '负责人用车'
+        when (select exists(select 1 from car_theme.wz_f_spc_car b where a.che_pai_hao = b.card_num and b.is_spec = '1')) then '特殊车辆'
+        when bao_fei = 1 then '报废'
+        else ''
+    end
+where
+    year_month = #{endYearMonth}
+""")
+    int updateCarLiChengMonthDiXiao(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆行驶里程月数据车辆基本信息
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update car.car_li_cheng_month a set
+che_liang_lai_yuan = b.che_liang_lai_yuan,
+che_liang_lei_xing = b.che_liang_lei_xing,
+che_liang_shi_yong_xing_zhi = b.che_liang_shi_yong_xing_zhi,
+che_liang_suo_shu_dan_wei = b.che_liang_suo_shu_dan_wei,
+first_unit = b.first_unit,
+second_unit = b.second_unit,
+third_unit = b.third_unit,
+area_no = b.area_no,
+area_name = b.area_name,
+city_no = b.city_no,
+city_name = b.city_name,
+area_name2 = b.area_name2,
+area_no2 = b.area_no2,
+city_id = b.city_id,
+city = b.city,
+district_id = b.district_id,
+district = b.district,
+car_new = b.car_new,
+car_move = b.car_move,
+car_move_yj = b.car_move_yj,
+car_move_ej = b.car_move_ej,
+car_move_sj = b.car_move_sj,
+car_new_year_month = b.car_new_year_month,
+car_new_date = b.car_new_date,
+deng_ji_ri_qi = b.deng_ji_ri_qi,
+last_first_unit = b.last_first_unit,
+car_move_yj_date = b.car_move_yj_date,
+car_move_yj_year_month = b.car_move_yj_year_month,
+no_info = 0
+from car.car_base_data_month b
+where a.year_month = b.year_month
+and a.che_pai_hao = b.che_pai_hao
+and a.year_month = #{endYearMonth}
+""")
+    int updateCarLiChengMonthBaseInfo(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆行驶里程月累计
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+t101 as (
+select
+    *
+from
+    car.workdays
+where
+    year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+),
+t102 as (
+select
+    *
+from
+    car.car_li_cheng_month
+where
+    year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+    and bao_fei = 0
+),
+t103 as (
+select
+    distinct on
+    (che_pai_hao) *
+from
+    t102
+order by
+    che_pai_hao,
+    year_month desc
+),
+t104 as (
+select
+    (
+    select
+        sum(workday)
+    from
+        t101 b
+    where
+        b.year_month >= (
+            case
+                when a.car_move_yj_date is not null then to_char((a.car_move_yj_date + interval '3 month')::date,
+            'YYYYMM')::int4
+            when a.car_new_date is not null then to_char((a.car_new_date + interval '3 month')::date,
+            'YYYYMM')::int4
+            else #{startYearMonth}
+        end
+        )) as workday_sum,
+    *
+from
+    t103 a
+),
+t105 as (
+select
+    che_pai_hao,
+        first_unit,
+        sum(case when car_move_yj_date is not null and year_month >= car_move_yj_year_month and year_month < to_char((car_move_yj_date + interval '3 month')::date, 'YYYYMM')::int4 then 0 when car_new_date is not null and year_month >= car_new_year_month and year_month < to_char((car_new_date + interval '3 month')::date, 'YYYYMM')::int4 then 0 else xing_shi_shi_chang end) as xing_shi_shi_chang_sum,
+        sum(case when car_move_yj_date is not null and year_month >= car_move_yj_year_month and year_month < to_char((car_move_yj_date + interval '3 month')::date, 'YYYYMM')::int4 then 0 when car_new_date is not null and year_month >= car_new_year_month and year_month < to_char((car_new_date + interval '3 month')::date, 'YYYYMM')::int4 then 0 else xing_shi_tian_shu end) as xing_shi_tian_shu_sum,
+        sum(case when car_move_yj_date is not null and year_month >= car_move_yj_year_month and year_month < to_char((car_move_yj_date + interval '3 month')::date, 'YYYYMM')::int4 then 0 when car_new_date is not null and year_month >= car_new_year_month and year_month < to_char((car_new_date + interval '3 month')::date, 'YYYYMM')::int4 then 0 else zong_li_cheng end) as zong_li_cheng_sum
+from
+    t102
+group by
+    che_pai_hao,
+    first_unit
+),
+t106 as (
+select
+t104.*,
+t105.xing_shi_shi_chang_sum,
+t105.xing_shi_tian_shu_sum,
+t105.zong_li_cheng_sum
+from t104 join t105 on t104.che_pai_hao = t105.che_pai_hao and t104.first_unit = t105.first_unit
+),
+t107 as (
+    select
+        case when workday_sum = 0 then null else zong_li_cheng_sum / workday_sum end as ri_jun_li_cheng_sum,
+        case when workday_sum = 0 then null else xing_shi_tian_shu_sum / workday_sum::numeric end as chu_qin_lv_sum,
+        #{endYearMonth} as stat_year_month,
+        *
+    from t106
+),
+t111 as (
+select
+    case
+        when (select exists(select 1 from car.car_bao_fei b where b.che_pai_hao = a.che_pai_hao and b.year_month <= a.stat_year_month)) then 0
+        when first_unit = '省公司本部' then 0
+        when position('建设部' in che_liang_suo_shu_dan_wei) > 0 then 0
+        when che_liang_lei_xing in ('特种车', '中型面包车(8-20座的面包车)', '大巴车') then 0
+        when che_liang_shi_yong_xing_zhi in ('特种车', '负责人用车') then 0
+        when (select exists(select 1 from car_theme.wz_f_spc_car b where a.che_pai_hao = b.card_num and b.is_spec = '1')) then 0
+        when car_move_yj_date is not null and stat_year_month >= car_move_yj_year_month and stat_year_month < to_char((car_move_yj_date + interval '3 month')::date, 'YYYYMM')::int4 then 0
+        when car_new_date is not null and stat_year_month >= car_new_year_month and stat_year_month < to_char((car_new_date + interval '3 month')::date, 'YYYYMM')::int4 then 0
+        when chu_qin_lv_sum < 0.5 and ri_jun_li_cheng_sum < 20 then 1
+        else 0
+    end as di_xiao_sum,
+    case
+        when (select exists(select 1 from car.car_bao_fei b where b.che_pai_hao = a.che_pai_hao and b.year_month <= a.stat_year_month)) then (select max(b.year_month) from car.car_bao_fei b where b.che_pai_hao = a.che_pai_hao and b.year_month <= a.stat_year_month) || '报废'
+        when first_unit = '省公司本部' then '省公司本部'
+        when position('建设部' in che_liang_suo_shu_dan_wei) > 0 then '建设部'
+        when che_liang_lei_xing = '特种车' then '特种车'
+        when che_liang_lei_xing = '中型面包车(8-20座的面包车)' then '中型面包车(8-20座的面包车)'
+        when che_liang_lei_xing = '大巴车' then '大巴车'
+        when che_liang_shi_yong_xing_zhi = '特种车' then '特种车'
+        when che_liang_shi_yong_xing_zhi = '负责人用车' then '负责人用车'
+        when (select exists(select 1 from car_theme.wz_f_spc_car b where a.che_pai_hao = b.card_num and b.is_spec = '1')) then '特殊车辆'
+        when car_move_yj_date is not null and stat_year_month >= car_move_yj_year_month and stat_year_month < to_char((car_move_yj_date + interval '3 month')::date, 'YYYYMM')::int4 then car_move_yj_year_month || '从' || last_first_unit || '调配到' || first_unit
+        when car_new_date is not null and stat_year_month >= car_new_year_month and stat_year_month < to_char((car_new_date + interval '3 month')::date, 'YYYYMM')::int4 then car_new_year_month || '新车'
+        else ''
+    end as di_xiao_sum_exclude_reason,
+    *
+from
+    t107 a
+)
+insert into car.car_li_cheng_lei_ji_month
+(
+year_month,
+che_pai_hao,
+di_xiao_sum,
+di_xiao_sum_exclude_reason,
+xing_shi_shi_chang_sum,
+xing_shi_tian_shu_sum,
+zong_li_cheng_sum,
+ri_jun_li_cheng_sum,
+chu_qin_lv_sum,
+workday_sum,
+che_liang_lei_xing,
+che_liang_lai_yuan,
+che_liang_shi_yong_xing_zhi,
+che_liang_suo_shu_dan_wei,
+first_unit,
+second_unit,
+third_unit,
+area_no,
+area_name,
+city_no,
+city_name,
+city_id,
+city,
+district_id,
+district,
+area_name2,
+area_no2,
+year_no,
+month_no,
+latest_year_month,
+car_new_year_month,
+car_move_yj_year_month
+)
+select
+stat_year_month as year_month,
+che_pai_hao,
+di_xiao_sum,
+di_xiao_sum_exclude_reason,
+xing_shi_shi_chang_sum,
+xing_shi_tian_shu_sum,
+zong_li_cheng_sum,
+ri_jun_li_cheng_sum,
+chu_qin_lv_sum,
+workday_sum,
+che_liang_lei_xing,
+che_liang_lai_yuan,
+che_liang_shi_yong_xing_zhi,
+che_liang_suo_shu_dan_wei,
+first_unit,
+second_unit,
+third_unit,
+area_no,
+area_name,
+city_no,
+city_name,
+city_id,
+city,
+district_id,
+district,
+area_name2,
+area_no2,
+left(cast(stat_year_month as varchar), 4)::int4 as year_no,
+right(cast(stat_year_month as varchar), 2)::int4 as month_no,
+year_month as latest_year_month,
+car_new_year_month,
+car_move_yj_year_month
+from t111
+""")
+    int insertCarLiChengLeiJiMonth(@Param("startYearMonth") Integer startYearMonth,
+                                   @Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆低效-累计算法
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car.car_di_xiao_month
+(
+year_month,
+    che_pai_hao,
+    xing_shi_shi_chang_sum,
+    xing_shi_tian_shu_sum,
+    zong_li_cheng_sum,
+    ri_jun_li_cheng_sum,
+    chu_qin_lv_sum,
+    workday_sum,
+    che_liang_lei_xing,
+    che_liang_lai_yuan,
+    che_liang_shi_yong_xing_zhi,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    city_id,
+    city,
+    district_id,
+    district,
+    area_name2,
+    area_no2,
+    year_no,
+    month_no
+)
+select
+    year_month,
+    che_pai_hao,
+    xing_shi_shi_chang_sum,
+    xing_shi_tian_shu_sum,
+    zong_li_cheng_sum,
+    ri_jun_li_cheng_sum,
+    chu_qin_lv_sum,
+    workday_sum,
+    che_liang_lei_xing,
+    che_liang_lai_yuan,
+    che_liang_shi_yong_xing_zhi,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    city_id,
+    city,
+    district_id,
+    district,
+    area_name2,
+    area_no2,
+    year_no,
+    month_no
+from
+    car.car_li_cheng_lei_ji_month
+where
+    year_month = #{endYearMonth}
+    and di_xiao_sum = 1
+""")
+    int insertCarDiXiaoMonth(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆违规数据
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car.car_wei_gui
+(
+che_liang_suo_shu_dan_wei,
+che_pai_hao,
+che_liang_lei_xing,
+che_liang_shi_yong_xing_zhi,
+bao_jing_qu_yu_miao_shu,
+bao_jing_gui_ze_miao_shu,
+yue_jie_shi_jian,
+shi_fou_zhi_xing_zhong_yue_jie,
+xiang_qing,
+first_unit,
+second_unit,
+third_unit,
+car_id,
+year_month,
+data_date,
+bao_fei,
+source,
+raw_che_pai_hao,
+area_no,
+area_name,
+city_no,
+city_name,
+area_no2,
+area_name2,
+city_id,
+city,
+district_id,
+district,
+year_no,
+month_no,
+che_pai_fail
+)
+select
+che_liang_suo_shu_dan_wei,
+che_pai_hao,
+che_liang_lei_xing,
+che_liang_shi_yong_xing_zhi,
+bao_jing_qu_yu_miao_shu,
+bao_jing_gui_ze_miao_shu,
+yue_jie_shi_jian,
+shi_fou_zhi_xing_zhong_yue_jie,
+xiang_qing,
+first_unit,
+second_unit,
+third_unit,
+car_id,
+year_month,
+data_date,
+bao_fei,
+source,
+raw_che_pai_hao,
+area_no,
+area_name,
+city_no,
+city_name,
+area_no2,
+area_name2,
+city_id,
+city,
+district_id,
+district,
+year_no,
+month_no,
+che_pai_fail
+from car.car_yue_jie
+where shi_fou_zhi_xing_zhong_yue_jie = '否'
+and year_month = #{endYearMonth}
+""")
+    int insertCarWeiGui(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆其他费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as qi_ta,
+    license_plate_number,
+    year_month
+from
+    car.car_qi_ta
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select distinct on
+    (license_plate_number,
+    year_month) *
+from
+    car.car_qi_ta
+where
+    year_month = #{endYearMonth}
+order by
+    license_plate_number,
+    year_month,
+    start_time desc
+),
+t103 as (
+select
+    t101.*,
+    t102.year_no,
+    t102.month_no,
+    t102.dept_id,
+    t102.first_unit,
+    t102.second_unit,
+    t102.third_unit,
+    t102.area_no,
+    t102.area_name,
+    t102.city_no,
+    t102.city_name,
+    t102.area_no2,
+    t102.area_name2,
+    t102.city_id,
+    t102.city,
+    t102.district_id,
+    t102.district
+from
+    t101
+join t102 on
+    t101.year_month = t102.year_month
+    and t101.license_plate_number = t102.license_plate_number
+)
+insert into car.car_fei_yong_month
+(
+    qi_ta,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+)
+select
+    qi_ta,
+    license_plate_number as che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    dept_id as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    t103 b
+where
+    not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.license_plate_number
+        and a.year_month = b.year_month)
+""")
+    int insertCarQiTa(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆年检费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as nian_jian_fei,
+    license_plate_number,
+    year_month
+from
+    car.car_nian_jian_fei
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select distinct on
+    (license_plate_number,
+    year_month) *
+from
+    car.car_nian_jian_fei
+where
+    year_month = #{endYearMonth}
+order by
+    license_plate_number,
+    year_month,
+    start_time desc
+),
+t103 as (
+select
+    t101.*,
+    t102.year_no,
+    t102.month_no,
+    t102.dept_id,
+    t102.first_unit,
+    t102.second_unit,
+    t102.third_unit,
+    t102.area_no,
+    t102.area_name,
+    t102.city_no,
+    t102.city_name,
+    t102.area_no2,
+    t102.area_name2,
+    t102.city_id,
+    t102.city,
+    t102.district_id,
+    t102.district
+from
+    t101
+join t102 on
+    t101.year_month = t102.year_month
+    and t101.license_plate_number = t102.license_plate_number
+)
+insert into car.car_fei_yong_month
+(
+    nian_jian_fei,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+)
+select
+    nian_jian_fei,
+    license_plate_number as che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    dept_id as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    t103 b
+where
+    not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.license_plate_number
+        and a.year_month = b.year_month)
+""")
+    int insertCarNianJianFei(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆保险费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(total_amount) as bao_xian,
+    license_plate_number,
+    year_month
+from
+    car.car_bao_xian
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select distinct on
+    (license_plate_number,
+    year_month) *
+from
+    car.car_bao_xian
+where
+    year_month = #{endYearMonth}
+order by
+    license_plate_number,
+    year_month,
+    start_time desc
+),
+t103 as (
+select
+    t101.*,
+    t102.year_no,
+    t102.month_no,
+    t102.dept_id,
+    t102.first_unit,
+    t102.second_unit,
+    t102.third_unit,
+    t102.area_no,
+    t102.area_name,
+    t102.city_no,
+    t102.city_name,
+    t102.area_no2,
+    t102.area_name2,
+    t102.city_id,
+    t102.city,
+    t102.district_id,
+    t102.district
+from
+    t101
+join t102 on
+    t101.year_month = t102.year_month
+    and t101.license_plate_number = t102.license_plate_number
+)
+insert into car.car_fei_yong_month
+(
+    bao_xian,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+)
+select
+    bao_xian,
+    license_plate_number as che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    dept_id as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    t103 b
+where
+    not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.license_plate_number
+        and a.year_month = b.year_month)
+""")
+    int insertCarBaoXian(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆路桥费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as lu_qiao,
+    license_plate_number,
+    year_month
+from
+    car.car_lu_qiao
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select distinct on
+    (license_plate_number,
+    year_month) *
+from
+    car.car_lu_qiao
+where
+    year_month = #{endYearMonth}
+order by
+    license_plate_number,
+    year_month,
+    start_time desc
+),
+t103 as (
+select
+    t101.*,
+    t102.year_no,
+    t102.month_no,
+    t102.dept_id,
+    t102.first_unit,
+    t102.second_unit,
+    t102.third_unit,
+    t102.area_no,
+    t102.area_name,
+    t102.city_no,
+    t102.city_name,
+    t102.area_no2,
+    t102.area_name2,
+    t102.city_id,
+    t102.city,
+    t102.district_id,
+    t102.district
+from
+    t101
+join t102 on
+    t101.year_month = t102.year_month
+    and t101.license_plate_number = t102.license_plate_number
+)
+insert into car.car_fei_yong_month
+(
+    lu_qiao,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+)
+select
+    lu_qiao,
+    license_plate_number as che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    dept_id as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    t103 b
+where
+    not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.license_plate_number
+        and a.year_month = b.year_month)
+""")
+    int insertCarLuQiao(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆维修费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as wei_xiu,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_wei_xiu
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select
+    sum(amount_excluding_tax) as wei_xiu,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_da_wei_xiu
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t201 as (
+select
+    (coalesce(t101.wei_xiu, 0) + coalesce(t102.wei_xiu, 0)) as wei_xiu,
+    t101.che_pai_hao,
+    t101.year_month
+from
+    t101
+join t102 on
+    t101.che_pai_hao = t102.che_pai_hao
+    and t101.year_month = t102.year_month
+),
+t202 as (
+select
+    *
+from
+    t101
+where
+    not exists (
+    select
+        1
+    from
+        t201
+    where
+        t201.che_pai_hao = t101.che_pai_hao
+        and t201.year_month = t101.year_month)
+),
+t203 as (
+select
+    *
+from
+    t102
+where
+    not exists (
+    select
+        1
+    from
+        t201
+    where
+        t201.che_pai_hao = t102.che_pai_hao
+        and t201.year_month = t102.year_month)
+),
+t301 as (
+select
+    *
+from
+    t201
+union all
+select
+    *
+from
+    t202
+union all
+select
+    *
+from
+    t203
+),
+t401 as (
+select
+    distinct on
+    (license_plate_number,
+    year_month) license_plate_number,
+    year_month,
+    year_no,
+    month_no,
+    organization as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    car.car_wei_xiu
+where
+    year_month = #{endYearMonth}
+),
+t402 as (
+select
+    distinct on
+    (license_plate_number,
+    year_month) license_plate_number,
+    year_month,
+    year_no,
+    month_no,
+    vehicle_unit as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    car.car_da_wei_xiu
+where
+    year_month = #{endYearMonth}
+),
+t403 as (
+select
+    *
+from
+    t401
+union all
+select
+    *
+from
+    t402
+),
+t404 as (
+select
+    distinct on
+    (license_plate_number,
+    year_month) *
+from
+    t403
+),
+t501 as (
+select
+    t301.*,
+    t404.year_no,
+    t404.month_no,
+    t404.che_liang_suo_shu_dan_wei,
+    t404.first_unit,
+    t404.second_unit,
+    t404.third_unit,
+    t404.area_no,
+    t404.area_name,
+    t404.city_no,
+    t404.city_name,
+    t404.area_no2,
+    t404.area_name2,
+    t404.city_id,
+    t404.city,
+    t404.district_id,
+    t404.district
+from
+    t301
+join t404 on
+    t301.che_pai_hao = t404.license_plate_number
+    and t301.year_month = t404.year_month
+)
+insert into car.car_fei_yong_month
+(
+    wei_xiu,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+)
+select
+    wei_xiu,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    t501 b
+where
+    not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.che_pai_hao
+        and a.year_month = b.year_month)
+""")
+    int insertCarWeiXiu(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆燃油费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as ran_you,
+    license_plate_number,
+    year_month
+from
+    car.car_ran_you
+where
+    year_month = #{endYearMonth}
+    and license_plate_number is not null
+    and license_plate_number != ''
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select distinct on
+    (license_plate_number,
+    year_month) *
+from
+    car.car_ran_you
+where
+    year_month = #{endYearMonth}
+order by
+    license_plate_number,
+    year_month,
+    start_time desc
+),
+t103 as (
+select
+    t101.*,
+    t102.year_no,
+    t102.month_no,
+    t102.vehicle_unit,
+    t102.first_unit,
+    t102.second_unit,
+    t102.third_unit,
+    t102.area_no,
+    t102.area_name,
+    t102.city_no,
+    t102.city_name,
+    t102.area_no2,
+    t102.area_name2,
+    t102.city_id,
+    t102.city,
+    t102.district_id,
+    t102.district
+from
+    t101
+join t102 on
+    t101.year_month = t102.year_month
+    and t101.license_plate_number = t102.license_plate_number
+)
+insert into car.car_fei_yong_month
+(
+    ran_you,
+    che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+)
+select
+    ran_you,
+    license_plate_number as che_pai_hao,
+    year_month,
+    year_no,
+    month_no,
+    vehicle_unit as che_liang_suo_shu_dan_wei,
+    first_unit,
+    second_unit,
+    third_unit,
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    area_no2,
+    area_name2,
+    city_id,
+    city,
+    district_id,
+    district
+from
+    t103 b
+where
+    not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.license_plate_number
+        and a.year_month = b.year_month)
+""")
+    int insertCarRanYou(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆租赁费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car.car_fei_yong_month
+(
+    zu_lin,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    che_pai_hao,
+    year_month
+)
+select
+    bu_han_shui_jin_e as zu_lin,
+    che_liang_suo_shu_dan_wei,
+    first_unit,
+    che_pai_hao,
+    year_month
+from
+    car.car_zu_lin b
+where
+    b.year_month = #{endYearMonth}
+    and b.che_pai_hao is not null
+    and b.che_pai_hao != ''
+    and not exists (
+    select
+        1
+    from
+        car.car_fei_yong_month a
+    where
+        a.che_pai_hao = b.che_pai_hao
+        and a.year_month = b.year_month)
+""")
+    int insertCarZuLin(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆其他费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as qi_ta,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_qi_ta
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+)
+update car.car_fei_yong_month a set qi_ta = b.qi_ta
+from t101 b
+where a.che_pai_hao = b.che_pai_hao and a.year_month = b.year_month
+""")
+    int updateCarQiTan(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆年检费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as nian_jian_fei,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_nian_jian_fei
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+)
+update car.car_fei_yong_month a set nian_jian_fei = b.nian_jian_fei
+from t101 b
+where a.che_pai_hao = b.che_pai_hao and a.year_month = b.year_month
+""")
+    int updateCarNianJianFei(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆保险费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(total_amount) as bao_xian,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_bao_xian
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+)
+update car.car_fei_yong_month a set bao_xian = b.bao_xian
+from t101 b
+where a.che_pai_hao = b.che_pai_hao and a.year_month = b.year_month
+""")
+    int updateCarBaoXian(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆路桥费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as lu_qiao,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_lu_qiao
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+)
+update car.car_fei_yong_month a set lu_qiao = b.lu_qiao
+from t101 b
+where a.che_pai_hao = b.che_pai_hao and a.year_month = b.year_month
+""")
+    int updateCarLuQiao(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆维修费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as wei_xiu,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_wei_xiu
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+),
+t102 as (
+select
+    sum(amount_excluding_tax) as wei_xiu,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_da_wei_xiu
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+),
+t201 as (
+select
+(coalesce(t101.wei_xiu, 0) + coalesce(t102.wei_xiu, 0)) as wei_xiu,
+t101.che_pai_hao,
+t101.year_month
+from t101 join t102 on t101.che_pai_hao = t102.che_pai_hao and t101.year_month = t102.year_month
+),
+t202 as (
+select * from t101
+where not exists (select 1 from t201 where t201.che_pai_hao = t101.che_pai_hao and t201.year_month = t101.year_month)
+),
+t203 as (
+select * from t102
+where not exists (select 1 from t201 where t201.che_pai_hao = t102.che_pai_hao and t201.year_month = t102.year_month)
+),
+t301 as (
+select * from t201
+union all
+select * from t202
+union all
+select * from t203
+)
+update car.car_fei_yong_month a set wei_xiu = b.wei_xiu
+from t301 b
+where a.che_pai_hao = b.che_pai_hao and a.year_month = b.year_month
+""")
+    int updateCarWeiXiu(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆燃油费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    sum(amount_excluding_tax) as ran_you,
+    license_plate_number as che_pai_hao,
+    year_month as year_month
+from
+    car.car_ran_you
+where year_month = #{endYearMonth}
+group by
+    license_plate_number,
+    year_month
+)
+update car.car_fei_yong_month a set ran_you = b.ran_you
+from t101 b
+where a.che_pai_hao = b.che_pai_hao and a.year_month = b.year_month
+""")
+    int updateCarRanYou(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆租赁费
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update
+    car.car_fei_yong_month a
+set
+    zu_lin = b.bu_han_shui_jin_e
+from
+    car.car_zu_lin b
+where
+    a.che_pai_hao = b.che_pai_hao
+    and a.year_month = b.year_month
+    and a.year_month = #{endYearMonth}
+""")
+    int updateCarZuLin(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆运行费总费用
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update
+    car.car_fei_yong_month
+set
+    yun_xing_fei = case
+        when ran_you is null
+        and bao_xian is null
+        and wei_xiu is null
+        and lu_qiao is null then null
+        else (coalesce(ran_you,
+        0) + coalesce(bao_xian,
+        0) + coalesce(wei_xiu,
+        0) + coalesce(lu_qiao,
+        0))
+    end,
+    zong_fei_yong = case
+        when ran_you is null
+        and bao_xian is null
+        and wei_xiu is null
+        and lu_qiao is null
+        and zu_lin is null
+        and nian_jian_fei is null
+        and qi_ta is null
+        then null
+        else (coalesce(ran_you,
+        0) + coalesce(bao_xian,
+        0) + coalesce(wei_xiu,
+        0) + coalesce(lu_qiao,
+        0) + coalesce(zu_lin,
+        0) + coalesce(nian_jian_fei,
+        0) + coalesce(qi_ta,
+        0))
+    end
+where year_month = #{endYearMonth}
+""")
+    int updateCarFeiYongMonthYunXingFeiZongFeiYong(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 更新车辆费用基本信息
+     * @param endYearMonth 账期
+     */
+    @Update("""
+update car.car_fei_yong_month a set
+che_liang_lai_yuan = coalesce((select che_liang_lai_yuan from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), che_liang_lai_yuan),
+che_liang_lei_xing = coalesce((select che_liang_lei_xing from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), che_liang_lei_xing),
+che_liang_shi_yong_xing_zhi = coalesce((select che_liang_shi_yong_xing_zhi from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), che_liang_shi_yong_xing_zhi),
+che_liang_suo_shu_dan_wei = coalesce((select che_liang_suo_shu_dan_wei from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), che_liang_suo_shu_dan_wei),
+first_unit = coalesce((select first_unit from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), first_unit),
+second_unit = coalesce((select second_unit from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), second_unit),
+third_unit = coalesce((select third_unit from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), third_unit),
+area_no = coalesce((select area_no from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), area_no),
+area_name = coalesce((select area_name from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), area_name),
+city_no = coalesce((select city_no from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), city_no),
+city_name = coalesce((select city_name from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), city_name),
+city_id = coalesce((select city_id from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), city_id),
+city = coalesce((select city from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), city),
+district_id = coalesce((select district_id from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), district_id),
+district = coalesce((select district from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), district),
+area_name2 = coalesce((select area_name2 from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), area_name2),
+area_no2 = coalesce((select area_no2 from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month order by b.year_month desc limit 1), area_no2),
+rui_xing = case when exists(select 1 from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month <= a.year_month) then 1 else 0 end,
+rui_xing_month = case when exists(select 1 from car.car_base_data_month b where a.che_pai_hao = b.che_pai_hao and b.year_month = a.year_month) then 1 else 0 end,
+year_no = left(cast(a.year_month as varchar), 4)::int4,
+month_no = right(cast(a.year_month as varchar), 2)::int4
+where year_month = #{endYearMonth}
+""")
+    int updateCarFeiYongMonthBaseInfo(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 判断是否有车辆基本信息、用车数据
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+    (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_base_data_month
+        where
+            year_month = #{endYearMonth}))
+    and (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_yong_che
+        where
+            year_month = #{endYearMonth}))
+""")
+    boolean hasCarBaseDataYongChe(@Param("endYearMonth") Integer endYearMonth);
+}

+ 1105 - 0
src/main/java/com/nokia/finance/tasks/dao/car/CarStrategyDao.java

@@ -0,0 +1,1105 @@
+package com.nokia.finance.tasks.dao.car;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+@Mapper
+public interface CarStrategyDao {
+    /**
+     * 插入高油耗车辆策略
+     *
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+t101 as (
+    select area_no,
+        area_name,
+        city_no,
+        city_name,
+        sum(ran_you) as ran_you_sum
+    from car.car_fei_yong_month
+    where first_unit != '省公司本部'
+        and position('建设部' in che_liang_suo_shu_dan_wei) = 0
+        and area_no is not null
+        and area_no != ''
+        and city_no is not null
+        and city_no != ''
+        and year_month >= #{startYearMonth}
+        and year_month <= #{endYearMonth}
+    group by area_no,
+        area_name,
+        city_no,
+        city_name
+),
+t102 as (
+    select area_no,
+        area_name,
+        city_no,
+        city_name,
+        sum(zong_li_cheng) as zong_li_cheng_sum
+    from car.car_li_cheng_month
+    where first_unit != '省公司本部'
+        and position('建设部' in che_liang_suo_shu_dan_wei) = 0
+        and area_no is not null
+        and area_no != ''
+        and city_no is not null
+        and city_no != ''
+        and year_month >= #{startYearMonth}
+        and year_month <= #{endYearMonth}
+    group by area_no,
+        area_name,
+        city_no,
+        city_name
+),
+t103 as (
+select
+t101.*,
+t102.zong_li_cheng_sum
+from t101
+join t102 on t101.area_no = t102.area_no and t101.city_no = t102.city_no
+),
+t104 as (
+    select *,
+        case when zong_li_cheng_sum = 0 then null else ran_you_sum / zong_li_cheng_sum * 100 end as bai_gong_li_you_fei
+    from t103
+    where ran_you_sum > 0 and zong_li_cheng_sum > 0
+),
+t105 as (
+    select *,
+        row_number() over (
+            order by bai_gong_li_you_fei desc
+        ) as bai_gong_li_you_fei_rank
+    from t104
+),
+t111 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_010_1' as kpi_code,
+        '县公司车辆燃油费' as kpi_name,
+        round(ran_you_sum, 2) as kpi_value,
+        bai_gong_li_you_fei_rank as sort
+    from t105
+),
+t112 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_010_2' as kpi_code,
+        '车辆行驶里程' as kpi_name,
+        round(zong_li_cheng_sum, 2) as kpi_value,
+        bai_gong_li_you_fei_rank as sort
+    from t105
+),
+t113 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_010_3' as kpi_code,
+        '百公里油耗' as kpi_name,
+        round(bai_gong_li_you_fei, 2) as kpi_value,
+        bai_gong_li_you_fei_rank as sort
+    from t105
+),
+t114 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_010_4' as kpi_code,
+        '排名' as kpi_name,
+        bai_gong_li_you_fei_rank as kpi_value,
+        bai_gong_li_you_fei_rank as sort
+    from t105
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+    union all
+    select * from t113
+    union all
+    select * from t114
+)
+insert into publish.car_high_fuel_consumption(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1,
+sort
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_010' as strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1,
+sort
+from t121
+order by sort,
+    kpi_code
+""")
+    int insertCarHighFuelConsumption(@Param("startYearMonth") Integer startYearMonth,
+                                     @Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询高油耗车辆策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_high_fuel_consumption where acct_date = #{endYearMonth} order by sort, kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getCarHighFuelConsumption(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入高修理车辆策略
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+t101 as (
+    select area_no,
+        area_name,
+        city_no,
+        city_name,
+        sum(wei_xiu) as wei_xiu_sum
+    from car.car_fei_yong_month
+    where first_unit != '省公司本部'
+        and position('建设部' in che_liang_suo_shu_dan_wei) = 0
+        and che_liang_lai_yuan = '自有车辆'
+        and area_no is not null
+        and area_no != ''
+        and city_no is not null
+        and city_no != ''
+        and year_month >= #{startYearMonth}
+        and year_month <= #{endYearMonth}
+    group by area_no,
+        area_name,
+        city_no,
+        city_name
+),
+t102 as (
+    select area_no,
+        area_name,
+        city_no,
+        city_name,
+        count(1) as total
+    from car.car_base_data_month
+    where first_unit != '省公司本部'
+        and position('建设部' in che_liang_suo_shu_dan_wei) = 0
+        and che_liang_lai_yuan = '自有车辆'
+        and area_no is not null
+        and area_no != ''
+        and city_no is not null
+        and city_no != ''
+        and year_month = #{endYearMonth}
+    group by area_no,
+        area_name,
+        city_no,
+        city_name
+),
+t103 as (
+select
+t101.*,
+t102.total
+from t101
+join t102 on t101.area_no = t102.area_no and t101.city_no = t102.city_no
+),
+t104 as (
+    select t103.*,
+        case when wei_xiu_sum is null then 0 else wei_xiu_sum / total end as wei_xiu_avg
+    from t103
+    where wei_xiu_sum > 0
+),
+t105 as (
+    select *,
+        row_number() over (
+            order by wei_xiu_avg desc
+        ) as wei_xiu_rank
+    from t104
+),
+t111 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_011_1' as kpi_code,
+        '自有车辆维修费' as kpi_name,
+        round(wei_xiu_sum, 2) as kpi_value,
+        wei_xiu_rank as sort
+    from t105
+),
+t112 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_011_2' as kpi_code,
+        '自有车辆数' as kpi_name,
+        total as kpi_value,
+        wei_xiu_rank as sort
+    from t105
+),
+t113 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_011_3' as kpi_code,
+        '车均维修费' as kpi_name,
+        round(wei_xiu_avg, 2) as kpi_value,
+        wei_xiu_rank as sort
+    from t105
+),
+t114 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_011_4' as kpi_code,
+        '排名' as kpi_name,
+        wei_xiu_rank as kpi_value,
+        wei_xiu_rank as sort
+    from t105
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+    union all
+    select * from t113
+    union all
+    select * from t114
+)
+insert into publish.car_high_repair(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1,
+sort
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_011' as strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1,
+sort
+from t121
+order by sort,
+    kpi_code
+""")
+    int insertCarHighRepair(@Param("startYearMonth") Integer startYearMonth,
+                            @Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询高修理车辆策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_high_repair where acct_date = #{endYearMonth} order by sort, kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getCarHighRepair(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入租赁车辆产生维修费策略
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+t101 as (
+    select *
+    from car.car_base_data_month
+    where che_liang_lai_yuan = '租赁车辆'
+    and area_no is not null
+    and area_no != ''
+    and city_no is not null
+    and city_no != ''
+    and year_month = #{startYearMonth}
+),
+t102 as (
+    select *
+    from car.car_fei_yong_month
+    where year_month >= #{startYearMonth}
+        and year_month <= #{endYearMonth}
+),
+t103 as (
+    select
+        area_no,
+        che_pai_hao,
+        sum(wei_xiu) as wei_xiu_sum
+    from t102
+    group by che_pai_hao, area_no
+),
+t104 as (
+select
+t101.*,
+t103.wei_xiu_sum
+from t101 join t103 on t101.che_pai_hao = t103.che_pai_hao and t101.area_no = t103.area_no
+where t103.wei_xiu_sum > 1800
+),
+t111 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_021_1' as kpi_code,
+        '车辆个数' as kpi_name,
+        count(1)::varchar as kpi_value
+    from t104
+    group by area_no, area_name, city_no, city_name
+),
+t112 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_021_2' as kpi_code,
+        '车牌号' as kpi_name,
+        che_pai_hao as kpi_value
+    from t104
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+)
+insert into publish.car_rental_repair(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_021' as strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1
+from t121
+order by
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    kpi_code
+""")
+    int insertCarRentalRepair(@Param("startYearMonth") Integer startYearMonth,
+                              @Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询租赁车辆产生维修费策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_rental_repair
+where acct_date = #{endYearMonth}
+order by
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getCarRentalRepair(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 判断是否有租赁车辆产生维修费策略需要的数据
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+    (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_base_data_month
+        where
+            year_month = #{endYearMonth}))
+    and (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_fei_yong_month
+        where
+            year_month = #{endYearMonth}))
+""")
+    boolean hasCarRentalRepair(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 判断是否有车辆违章未处理策略需要的数据
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select exists (select 1 from car.car_wei_zhang where year_month = #{endYearMonth})
+""")
+    boolean hasCarViolationUnprocessed(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆违章未处理策略
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+t101 as (
+select
+distinct on (che_pai_hao, area_no, city_no) *
+from
+    car.car_wei_zhang_chang_qi
+where
+    area_no is not null
+    and area_no != ''
+    and city_no is not null
+    and city_no != ''
+    and year_month = #{endYearMonth}
+),
+t111 as (
+    select 
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_022_1' as kpi_code,
+        '车辆个数' as kpi_name,
+        count(1)::varchar as kpi_value
+    from t101
+    group by area_no, area_name, city_no, city_name
+),
+t112 as (
+    select 
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_022_2' as kpi_code,
+        '车牌号' as kpi_name,
+        che_pai_hao as kpi_value
+    from t101
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+)
+insert into publish.car_violation_unprocessed(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_022' as strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1
+from t121
+order by
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    kpi_code
+""")
+    int insertCarViolationUnprocessed(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询车辆违章未处理策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_violation_unprocessed
+where acct_date = #{endYearMonth}
+order by
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getCarViolationUnprocessed(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入违规车辆策略
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    area_no,
+    area_name,
+    count(1) as total
+from
+    car.car_wei_gui
+where
+    area_no is not null
+    and area_no != ''
+    and city_no is not null
+    and city_no != ''
+    and year_month = #{endYearMonth}
+group by
+    area_name, area_no
+),
+t102 as (
+select * from car.car_wei_gui
+where
+    area_no is not null
+    and area_no != ''
+    and city_no is not null
+    and city_no != ''
+    and year_month = #{endYearMonth}
+),
+t111 as (
+    select
+        area_no,
+        area_name,
+        'kpi_30059_012_1' as kpi_code,
+        '违规次数' as kpi_name,
+        total::varchar as kpi_value
+    from t101
+),
+t112 as (
+    select
+        area_no,
+        area_name,
+        'kpi_30059_012_2' as kpi_code,
+        '车牌号' as kpi_name,
+        che_pai_hao as kpi_value
+    from t102
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+)
+insert into publish.car_wdyj(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_012' as strategy_code,
+area_no,
+area_name,
+'' as city_no,
+'' as city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1
+from t121
+order by
+    area_no,
+    area_name,
+    kpi_code,
+    kpi_value
+""")
+    int insertCarWdyj(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询违规车辆策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_wdyj
+where acct_date = #{endYearMonth}
+order by
+    area_no,
+    area_name,
+    kpi_code,
+    kpi_value
+""")
+    List<LinkedHashMap<String, Object>> getCarWdyj(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 判断是否有低效车辆策略需要的数据
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+    (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_base_data_month
+        where
+            year_month = #{endYearMonth}))
+    and (
+    select
+        exists (
+        select
+            1
+        from
+            car.car_li_cheng_month
+        where
+            year_month = #{endYearMonth}))
+""")
+    boolean hasCarInefficiency(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆低效占比策略
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select * from car.car_di_xiao_month
+where
+    area_no is not null
+    and area_no != ''
+    and year_month = #{endYearMonth}
+),
+t102 as (
+    select area_no,
+        area_name,
+        count(1) as di_xiao_count
+    from t101
+    group by area_no,
+        area_name
+),
+t103 as (
+    select area_no,
+        area_name,
+        count(1) as total
+    from car.car_base_data_month
+where
+    area_no is not null
+    and area_no != ''
+    and year_month = #{endYearMonth}
+    group by area_no,
+        area_name
+),
+t104 as (
+    select
+    t102.*,
+    t103.total,
+    t102.di_xiao_count / t103.total::numeric * 100 as di_xiao_percent
+    from t102
+        join t103 on t102.area_no = t103.area_no
+),
+t111 as (
+    select
+        area_no,
+        area_name,
+        'kpi_30059_014_1' as kpi_code,
+        '低效车个数' as kpi_name,
+        di_xiao_count as kpi_value
+    from t104
+),
+t112 as (
+    select
+        area_no,
+        area_name,
+        'kpi_30059_014_2' as kpi_code,
+        '低效车占比' as kpi_name,
+        round(di_xiao_percent, 2) as kpi_value
+    from t104
+    order by area_no
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+)
+insert into publish.car_inefficiency_percent(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_014' as strategy_code,
+area_no,
+area_name,
+'' as city_no,
+'' as city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1
+from t121
+order by area_no,
+    kpi_code
+""")
+    int insertCarInefficiencyPercent(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询车辆低效占比策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_inefficiency_percent
+where acct_date = #{endYearMonth}
+order by
+    area_no,
+    kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getCarInefficiencyPercent(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆低效区县策略
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select * from car.car_di_xiao_month
+where
+    area_no is not null
+    and area_no != ''
+    and city_no is not null
+    and city_no != ''
+    and year_month = #{endYearMonth}
+),
+t111 as (
+    select 
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_013_1' as kpi_code,
+        '低效车个数' as kpi_name,
+        count(1)::varchar as kpi_value
+    from t101
+    group by area_no,
+        area_name,
+        city_no,
+        city_name
+),
+t112 as (
+    select
+        area_no,
+        area_name,
+        city_no,
+        city_name,
+        'kpi_30059_013_2' as kpi_code,
+        '车牌号' as kpi_name,
+        che_pai_hao as kpi_value
+    from t101
+),
+t121 as (
+    select * from t111
+    union all
+    select * from t112
+)
+insert into publish.car_inefficiency_qx(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+)
+select
+#{endYearMonth} as acct_date,
+'30059' as dept_code,
+'河北省分公司财务部' as dept_name,
+'30059_013' as strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+'' as sale_no,
+'' as sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+'' as kpi_type,
+'' as remark_1
+from t121
+order by area_no,
+    city_no,
+    kpi_code
+""")
+    int insertCarInefficiencyQx(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询车辆低效占比策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+remark_1
+from publish.car_inefficiency_qx
+where acct_date = #{endYearMonth}
+order by
+    area_no,
+    city_no,
+    kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getCarInefficiencyQx(@Param("endYearMonth") Integer endYearMonth);
+}

+ 603 - 0
src/main/java/com/nokia/finance/tasks/dao/gdc/car/GdcCarProcedureDao.java

@@ -0,0 +1,603 @@
+package com.nokia.finance.tasks.dao.gdc.car;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+/**
+ * gdc车辆php数据库存储过程
+ */
+@Mapper
+public interface GdcCarProcedureDao {
+    /**
+     * 插入车辆报废记录
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car_theme.wz_f_car_scrap
+(
+scrap_date,
+card_num,
+city,
+dpt_sec,
+grid,
+year_info,
+month_info
+)
+select
+bao_fei_ri_qi as scrap_date,
+che_pai_hao as card_num,
+first_unit as city,
+second_unit as dpt_sec,
+third_unit as grid,
+date_part('year', bao_fei_ri_qi) as year_info,
+date_part('month', bao_fei_ri_qi) as month_info
+from car.car_bao_fei
+where year_month = #{endYearMonth}
+""")
+    int insertCarScrap(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入车辆基本信息
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car_theme.wz_f_car_info
+(
+    year_month,
+    car_id,
+    card_num,
+    city,
+    dpt_sec,
+    grid,
+    emissions,
+    car_type,
+    enabled_date,
+    using_tag,
+    asset_id,
+    self_rent,
+    is_special_car,
+    emissions_type,
+    oil_type,
+    env_lev,
+    engine_id,
+    fra_id,
+    init_mileage,
+    own_dpt,
+    driving_id,
+    car_state,
+    car_brand,
+    car_new,
+    car_move,
+    allocation_in_date,
+    allocation_remark
+)
+select
+    year_month,
+    year_month || '-' || che_pai_hao as car_id,
+    che_pai_hao as card_num,
+    first_unit as city,
+    second_unit as dpt_sec,
+    third_unit as grid,
+    pai_liang as emissions,
+    che_liang_lei_xing as car_type,
+    deng_ji_ri_qi as enabled_date,
+    che_liang_shi_yong_xing_zhi as using_tag,
+    zi_chan_bian_hao as asset_id,
+    che_liang_lai_yuan as self_rent,
+    case
+        when first_unit = '省公司本部'
+        or position('建设部' in che_liang_suo_shu_dan_wei) > 0
+        or che_liang_lei_xing = '特种车'
+        or che_liang_shi_yong_xing_zhi in ('特种车', '负责人用车')
+        or che_liang_lei_xing in ('特种车', '中型面包车(8-20座的面包车)', '大巴车') then 1
+        else 0
+    end as is_special_car,
+    pai_liang_lei_xing as emissions_type,
+    ran_you_biao_hao as oil_type,
+    huan_bao_deng_ji as env_lev,
+    fa_dong_ji_hao as engine_id,
+    che_jia_hao as fra_id,
+    chu_shi_li_cheng as init_mileage,
+    che_liang_suo_shu_dan_wei as own_dpt,
+    xing_shi_zheng_hao as driving_id,
+    che_liang_zhuang_tai as car_state,
+    che_liang_pin_pai as car_brand,
+    car_new,
+    case
+        when car_move_yj_year_month is null then 0
+        else 1
+    end as car_move,
+    case
+        when car_move_yj_year_month is null then car_new_year_month
+        else car_move_yj_year_month
+    end as allocation_in_date,
+    case
+        when last_first_unit is not null
+        and last_first_unit != ''
+        and car_move_yj_year_month is not null then to_char(car_move_yj_date,
+        'YYYY年MM月') || '从' || last_first_unit || '调配到' || first_unit
+    end as allocation_remark
+from
+    car.car_base_data_month
+where
+    year_month = #{endYearMonth}
+""")
+    int insertCarInfo(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入一车一表
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select * from car.car_base_data_month where year_month = #{endYearMonth}
+),
+t102 as (
+select * from car.car_fei_yong_month where year_month = #{endYearMonth}
+),
+t103 as (
+select * from car.car_li_cheng_month where year_month = #{endYearMonth}
+),
+t104 as (
+select
+year_month,
+che_pai_hao,
+count(1) as wei_gui_count
+from car.car_wei_gui
+where year_month = #{endYearMonth}
+group by year_month, che_pai_hao
+),
+t105 as (
+select
+year_month,
+che_pai_hao,
+count(1) as yue_jie_count
+from car.car_yue_jie
+where year_month = #{endYearMonth}
+group by year_month, che_pai_hao
+),
+t201 as (
+select
+t101.*,
+t102.ran_you,
+t102.wei_xiu,
+t102.lu_qiao,
+t102.zu_lin,
+t102.bao_xian,
+t102.nian_jian_fei,
+t102.qi_ta,
+t102.zong_fei_yong,
+(select sum(zong_li_cheng) from car.car_li_cheng_month b where t101.che_pai_hao = b.che_pai_hao and b.year_month <= t101.year_month) as zong_li_cheng_total,
+t103.zong_li_cheng,
+t103.xing_shi_tian_shu,
+t103.workday,
+t103.chu_qin_lv,
+t103.di_xiao,
+t104.wei_gui_count,
+t105.yue_jie_count
+from t101
+left join t102 on t101.che_pai_hao = t102.che_pai_hao and t101.year_month = t102.year_month
+left join t103 on t101.che_pai_hao = t103.che_pai_hao and t101.year_month = t103.year_month
+left join t104 on t101.che_pai_hao = t104.che_pai_hao and t101.year_month = t104.year_month
+left join t105 on t101.che_pai_hao = t105.che_pai_hao and t101.year_month = t105.year_month
+),
+t202 as (
+select
+t201.*,
+case when zong_li_cheng = 0 then null else ran_you / zong_li_cheng * 100 end as bai_gong_li_you_fei,
+case when zong_li_cheng = 0 then null else wei_xiu / zong_li_cheng * 100 end as bai_gong_li_wei_xiu,
+case when zong_li_cheng = 0 then null else zong_fei_yong / zong_li_cheng * 100 end as bai_gong_li_fei_yong
+from t201
+)
+insert into car_theme.wz_f_one_car_one_table
+(
+car_id,
+che_pai_hao,
+current_mileage,
+car_status,
+year_info,
+month_info,
+oil_costs,
+repair_costs,
+road_bridge_costs,
+rent_costs,
+insurance_costs,
+year_check_costs,
+other_costs,
+sum_costs,
+sum_mileage,
+attendance,
+is_inefficient,
+oil_per_km,
+repair_per_km,
+sum_costs_per_km,
+violations_times,
+cross_border_times,
+attend_days,
+work_days,
+fuel_cost_per_l
+)
+select
+    year_month || '-' || che_pai_hao as car_id,
+    che_pai_hao,
+    round(coalesce(zong_li_cheng_total, 0) + coalesce(chu_shi_li_cheng, 0), 2) as current_mileage,
+    che_liang_zhuang_tai as car_status,
+    left(cast(year_month as varchar), 4)::int4 as year_info,
+    right(cast(year_month as varchar), 2)::int4 as month_info,
+    case when ran_you is null then 0 else round(ran_you, 2) end as oil_costs,
+    case when wei_xiu is null then 0 else round(wei_xiu, 2) end as repair_costs,
+    case when lu_qiao is null then 0 else round(lu_qiao, 2) end as road_bridge_costs,
+    case when zu_lin is null then 0 else round(zu_lin, 2) end as rent_costs,
+    case when bao_xian is null then 0 else round(bao_xian, 2) end as insurance_costs,
+    case when nian_jian_fei is null then 0 else round(nian_jian_fei, 2) end as year_check_costs,
+    case when qi_ta is null then 0 else round(qi_ta, 2) end as other_costs,
+    case when zong_fei_yong is null then 0 else round(zong_fei_yong, 2) end as sum_costs,
+    case when zong_li_cheng is null then 0 else round(zong_li_cheng, 2) end as sum_mileage,
+    round(chu_qin_lv, 4) as attendance,
+    di_xiao as is_inefficient,
+    round(bai_gong_li_you_fei, 2) as oil_per_km,
+    round(bai_gong_li_wei_xiu, 2) as repair_per_km,
+    round(bai_gong_li_fei_yong, 2) as sum_costs_per_km,
+    case when wei_gui_count is null then 0 else wei_gui_count end as violations_times,
+    case when yue_jie_count is null then 0 else yue_jie_count end as cross_border_times,
+    case when xing_shi_tian_shu is null then 0 else xing_shi_tian_shu end as attend_days,
+    workday as work_days,
+    8.7 as fuel_cost_per_l
+from t202
+""")
+    int insertOneCarOneTable(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入违规车辆
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car_theme.wz_f_un_dispatch_orders_cross_border
+(
+statistical_month,
+card_num,
+city,
+dpt_sec,
+grid,
+cross_border_t,
+alarm_area_des,
+alarm_rule_des,
+is_working,
+car_type,
+using_tag
+)
+select
+year_month,
+che_pai_hao,
+first_unit,
+second_unit,
+third_unit,
+yue_jie_shi_jian,
+bao_jing_qu_yu_miao_shu,
+bao_jing_gui_ze_miao_shu,
+shi_fou_zhi_xing_zhong_yue_jie,
+che_liang_lei_xing,
+che_liang_shi_yong_xing_zhi
+from car.car_wei_gui
+where year_month = #{endYearMonth}
+""")
+    int insertCarWeiGui(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入无单用车报警
+     * @param endYearMonth 账期
+     */
+    @Update("""
+insert into car_theme.wz_f_un_dispatch_orders_details
+(
+statistical_month,
+card_num,
+city,
+dpt_sec,
+grid,
+own_dpt,
+violation_time_start,
+violation_time_end,
+violation_time_duration
+)
+select
+year_month as statistical_month,
+che_pai_hao as card_num,
+first_unit as city,
+second_unit as dpt_sec,
+third_unit as grid,
+che_liang_suo_shu_dan_wei as own_dpt,
+wei_gui_kai_shi_shi_jian as violation_time_start,
+wei_gui_jie_shu_shi_jian as violation_time_end,
+wei_gui_chi_xu_shi_jian as violation_time_duration
+from car.car_wu_dan_yong_che
+where year_month = #{endYearMonth}
+""")
+    int insertCarWuDanYongCheBaoJing(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入无派单越界统计
+     * @param startYearMonth 开始年月
+     * @param endYearMonth 结束年月
+     */
+    @Update("""
+with
+t101 as (
+select
+    count(1) as total
+from
+    car.car_base_data_month
+where
+    year_month = #{endYearMonth}
+),
+t102 as (
+select
+    count(1) as cccs
+from
+    car.car_yong_che
+where
+    year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+),
+t103 as (
+select
+    count(1) as wdycbjcs
+from
+    car.car_wu_dan_yong_che
+where
+    year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+),
+t104 as (
+select
+    count(1) as yjcs
+from
+    car.car_yue_jie
+where
+    year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+),
+t105 as (
+select
+    count(1) as wpdyjcs
+from
+    car.car_wei_gui
+where
+    year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+),
+t109 as (
+select
+'全省' as first_unit,
+'' as second_unit,
+t101.total,
+t102.cccs,
+t103.wdycbjcs,
+t104.yjcs,
+t105.wpdyjcs
+from t101
+cross join t102
+cross join t103
+cross join t104
+cross join t105
+),
+t201 as (
+select
+    first_unit,
+    count(1) as total
+from
+    car.car_base_data_month
+where
+    first_unit is not null
+    and first_unit != ''
+    and year_month = #{endYearMonth}
+group by
+    first_unit
+),
+t202 as (
+select
+    first_unit,
+    count(1) as cccs
+from
+    car.car_yong_che
+where
+    first_unit is not null
+    and first_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit
+),
+t203 as (
+select
+    first_unit,
+    count(1) as wdycbjcs
+from
+    car.car_wu_dan_yong_che
+where
+    first_unit is not null
+    and first_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit
+),
+t204 as (
+select
+    first_unit,
+    count(1) as yjcs
+from
+    car.car_yue_jie
+where
+    first_unit is not null
+    and first_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit
+),
+t205 as (
+select
+    first_unit,
+    count(1) as wpdyjcs
+from
+    car.car_wei_gui
+where
+    first_unit is not null
+    and first_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit
+),
+t209 as (
+select
+t201.first_unit,
+'' as second_unit,
+t201.total,
+t202.cccs,
+t203.wdycbjcs,
+t204.yjcs,
+t205.wpdyjcs
+from t201
+left join t202 on t201.first_unit = t202.first_unit
+left join t203 on t201.first_unit = t203.first_unit
+left join t204 on t201.first_unit = t204.first_unit
+left join t205 on t201.first_unit = t205.first_unit
+order by t201.first_unit
+),
+t301 as (
+select
+    first_unit,
+    second_unit,
+    count(1) as total
+from
+    car.car_base_data_month
+where
+    first_unit is not null
+    and first_unit != ''
+    and second_unit is not null
+    and second_unit != ''
+    and year_month = #{endYearMonth}
+group by
+    first_unit, second_unit
+),
+t302 as (
+select
+    first_unit,
+    second_unit,
+    count(1) as cccs
+from
+    car.car_yong_che
+where
+    first_unit is not null
+    and first_unit != ''
+    and second_unit is not null
+    and second_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit, second_unit
+),
+t303 as (
+select
+    first_unit,
+    second_unit,
+    count(1) as wdycbjcs
+from
+    car.car_wu_dan_yong_che
+where
+    first_unit is not null
+    and first_unit != ''
+    and second_unit is not null
+    and second_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit, second_unit
+),
+t304 as (
+select
+    first_unit,
+    second_unit,
+    count(1) as yjcs
+from
+    car.car_yue_jie
+where
+    first_unit is not null
+    and first_unit != ''
+    and second_unit is not null
+    and second_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit, second_unit
+),
+t305 as (
+select
+    first_unit,
+    second_unit,
+    count(1) as wpdyjcs
+from
+    car.car_wei_gui
+where
+    first_unit is not null
+    and first_unit != ''
+    and second_unit is not null
+    and second_unit != ''
+    and year_month >= #{startYearMonth}
+    and year_month <= #{endYearMonth}
+group by
+    first_unit, second_unit
+),
+t309 as (
+select
+t301.first_unit,
+t301.second_unit,
+t301.total,
+t302.cccs,
+t303.wdycbjcs,
+t304.yjcs,
+t305.wpdyjcs
+from t301
+left join t302 on t301.first_unit = t302.first_unit and t301.second_unit = t302.second_unit
+left join t303 on t301.first_unit = t303.first_unit and t301.second_unit = t303.second_unit
+left join t304 on t301.first_unit = t304.first_unit and t301.second_unit = t304.second_unit
+left join t305 on t301.first_unit = t305.first_unit and t301.second_unit = t305.second_unit
+order by t301.first_unit
+),
+t401 as (
+select * from t109
+union all
+select * from t209
+union all
+select * from t309
+)
+insert into car_theme.wz_f_un_dispatch_orders_cross_border_statistics
+(
+statistical_month,
+city,
+dpt_sec,
+car_num,
+departures_car_num_sum,
+un_dispatch_num_sum,
+cross_border__num_sum,
+un_dispatch_cross_border_num_sum
+)
+select
+#{endYearMonth} as statistical_month,
+first_unit as city,
+case when second_unit = '' then null else second_unit end as dpt_sec,
+total as car_num,
+coalesce(cccs, 0) as departures_car_num_sum,
+coalesce(wdycbjcs, 0) as un_dispatch_num_sum,
+coalesce(yjcs, 0) as cross_border__num_sum,
+coalesce(wpdyjcs, 0) as un_dispatch_cross_border_num_sum
+from t401
+where first_unit not in ('华北基地建设部', '雄安基地建设部')
+""")
+    int insertCarWuPaiDanYueJieTongJi(@Param("startYearMonth") Integer startYearMonth,
+                                      @Param("endYearMonth") Integer endYearMonth);
+}

+ 104 - 0
src/main/java/com/nokia/finance/tasks/dao/gdc/house/GdcHouseProcedureDao.java

@@ -0,0 +1,104 @@
+package com.nokia.finance.tasks.dao.gdc.house;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Update;
+
+@Mapper
+public interface GdcHouseProcedureDao {
+    /**
+     * 更新自有房产维修
+     */
+    @Update("""
+with
+t101 as (
+select * from house.building_month where year_month = (select max(year_month) from house.building_month)
+)
+insert into house_theme.wz_f_housermaintenance_maintenance_cost_detailed (
+     building_id,
+     repair_type,
+     repair_content,
+     erp_credited_amount,
+     province,
+     city,
+     county,
+     building_address_number,
+     building_name_alias,
+     standard_address,
+     city_grade,
+     city_area,
+     district,
+     land_assets,
+     building_address_id,
+     building_alias,
+     building_rate,
+     building_source,
+     getdate,
+     building_startyear,
+     investment_entity,
+     management_hierarchy,
+     building_structure,
+     total_number_of_floors,
+     asset_code,
+     asts_labe,
+     use_state,
+     building_use,
+     ownership_status,
+     building_floor_area,
+     building_area,
+     building_area_use_area,
+     building_area_rent_area,
+     building_area_idel_area,
+     building_area_unavailable,
+     use_area,
+     use_area_self_use_area,
+     use_area_rent_area,
+     use_area_idel_area,
+     use_area_unavailable_area,
+     statistical_month
+)
+select
+     t1.jz_jzid,
+     t1.repair_type,
+     t1.content_category,
+     t1.final_cost,
+     '河北',
+     t1.area_name,
+     t1.city_name,
+     t2.site_num,
+     t2.site_name,
+     t2.address,
+     t2.city_level,
+     t2.city_region,
+     t2.area_sector,
+     t2.has_land,
+     t2.site_id,
+     t2.building_name,
+     t2.housing_acquisition_rate,
+     t2.housing_source,
+     t2.acquisition_date,
+     t2.house_year_began,
+     t2.investor,
+     t2.management_level,
+     t2.building_structure,
+     t2.total_floors,
+     t2.assets_num,
+     t2.assets_tag_num,
+     t2.usage_status,
+     t2.building_use,
+     t2.ownership_status,
+     t2.floor_area,
+     t2.building_area,
+     t2.building_area_self_use,
+     t2.building_area_rent,
+     t2.building_area_idle,
+     t2.building_area_unusable,
+     t2.usable_area,
+     t2.usable_area_self_use,
+     t2.usable_area_rent,
+     t2.usable_area_idle,
+     t2.usable_area_unusable,
+     t1.year_month
+from house.building_repair_month t1 left join t101 t2 on t1.jz_jzid = t2.building_id and t1.year_month = 202402
+""")
+    int insertHousermaintenanceMaintenanceCostDetailed();
+}

+ 231 - 0
src/main/java/com/nokia/finance/tasks/dao/house/HouseFcdpDao.java

@@ -0,0 +1,231 @@
+package com.nokia.finance.tasks.dao.house;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+@Mapper
+public interface HouseFcdpDao {
+    /**
+     * 插入房产大屏建筑面积统计
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t1 as (
+select
+    '全省' as city,
+    sum(case when building_use = '综合用房' then building_area else 0 end) as area_synthesis,
+    sum(case when building_use = '设备用房' then building_area else 0 end) as area_equipment,
+    sum(case when building_use = '营销用房' then building_area else 0 end) as area_marketing,
+    sum(case when building_use = '附属用房' then building_area else 0 end) as area_affiliate,
+    sum(case when building_use = '行政用房' then building_area else 0 end) as area_administration,
+    sum(case when building_use not in ('综合用房', '设备用房', '营销用房', '附属用房', '行政用房') then building_area else 0 end) as area_other,
+    sum(building_area_self_use) as area_self_use,
+    sum(building_area_rent) as area_rent,
+    sum(building_area) - sum(building_area_self_use) - sum(building_area_rent) as area_unused,
+    sum(building_area) as area_total
+from
+    house.building_month
+where
+    year_month = #{endYearMonth}
+),
+t2 as (
+select
+    city,
+    sum(case when building_use = '综合用房' then building_area else 0 end) as area_synthesis,
+    sum(case when building_use = '设备用房' then building_area else 0 end) as area_equipment,
+    sum(case when building_use = '营销用房' then building_area else 0 end) as area_marketing,
+    sum(case when building_use = '附属用房' then building_area else 0 end) as area_affiliate,
+    sum(case when building_use = '行政用房' then building_area else 0 end) as area_administration,
+    sum(case when building_use not in ('综合用房', '设备用房', '营销用房', '附属用房', '行政用房') then building_area else 0 end) as area_other,
+    sum(building_area_self_use) as area_self_use,
+    sum(building_area_rent) as area_rent,
+    sum(building_area) - sum(building_area_self_use) - sum(building_area_rent) as area_unused,
+    sum(building_area) as area_total
+from
+    house.building_month
+where
+    year_month = #{endYearMonth}
+    and city is not null
+    and city != ''
+group by city
+),
+t3 as (
+select * from t1
+union all
+select * from t2
+)
+insert into publish.house_building_area_stat
+(
+stat_date,
+city,
+area_self_use,
+area_rent,
+area_unused,
+percent_synthesis,
+percent_equipment,
+percent_marketing,
+percent_affiliate,
+percent_administration,
+percent_other,
+percent_self_use,
+percent_rent,
+percent_unused
+)
+select
+    #{endYearMonth} as stat_date,
+    city,
+    round(area_self_use / 10000, 2) as area_self_use,
+    round(area_rent / 10000, 2) as area_rent,
+    round(area_unused / 10000, 2) as area_unused,
+    round(area_synthesis / area_total * 100, 2) as percent_synthesis,
+    round(area_equipment / area_total * 100, 2) as percent_equipment,
+    round(area_marketing / area_total * 100, 2) as percent_marketing,
+    round(area_affiliate / area_total * 100, 2) as percent_affiliate,
+    round(area_administration / area_total * 100, 2) as percent_administration,
+    round(area_other / area_total * 100, 2) as percent_other,
+    round(area_self_use / area_total * 100, 2) as percent_self_use,
+    round(area_rent / area_total * 100, 2) as percent_rent,
+    round(area_unused / area_total * 100, 2) as percent_unused
+from t3
+""")
+    int insertHouseBuildingAreaStat(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询房产大屏建筑面积统计
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select * from publish.house_building_area_stat where stat_date = #{endYearMonth}
+""")
+    List<LinkedHashMap<String, Object>> getHouseBuildingAreaStat(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 插入房产大屏建筑和土地数量统计
+     * @param endYearMonth 账期
+     */
+    @Update("""
+with
+t101 as (
+select
+    city,
+    count(1) as building_count
+from
+    house.building_month
+where
+    year_month = #{endYearMonth}
+    and city is not null
+    and city != ''
+group by
+    city
+),
+t102 as (
+select
+    city,
+    count(1) as land_count
+from
+    house.land_month
+where
+    year_month = #{endYearMonth}
+    and city is not null
+    and city != ''
+group by
+    city
+),
+t103 as (
+select
+    t101.city,
+    '' as district,
+    t101.building_count,
+    t102.land_count
+from
+    t101
+join t102 on
+    t101.city = t102.city
+order by
+    t101.city
+),
+t201 as (
+select
+    city,
+    district,
+    count(1) as building_count
+from
+    house.building_month
+where
+    year_month = #{endYearMonth}
+    and city is not null
+    and city != ''
+    and district is not null
+    and district != ''
+group by
+    city,
+    district
+),
+t202 as (
+select
+    city,
+    district,
+    count(1) as land_count
+from
+    house.land_month
+where
+    year_month = #{endYearMonth}
+    and city is not null
+    and city != ''
+    and district is not null
+    and district != ''
+group by
+    city,
+    district
+),
+t203 as (
+select
+    t201.city,
+    t201.district,
+    t201.building_count,
+    t202.land_count
+from
+    t201
+join t202 on
+    t201.city = t202.city and t201.district = t202.district
+order by
+    t201.city, t201.district
+),
+t301 as (
+select * from t103
+union all
+select * from t203
+)
+insert into publish.house_building_land_count
+(
+stat_date,
+city,
+district,
+building_count,
+land_count
+)
+select
+#{endYearMonth} as stat_date,
+city,
+district,
+building_count,
+land_count
+from t301
+""")
+    int insertHouseBuildingLandCount(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询房产大屏建筑面积统计
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select * from publish.house_building_land_count where stat_date = #{endYearMonth}
+""")
+    List<LinkedHashMap<String, Object>> getHouseBuildingLandCount(@Param("endYearMonth") Integer endYearMonth);
+}

+ 316 - 0
src/main/java/com/nokia/finance/tasks/dao/house/HouseStrategyDao.java

@@ -0,0 +1,316 @@
+package com.nokia.finance.tasks.dao.house;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+@Mapper
+public interface HouseStrategyDao {
+    /**
+     * 判断是否有建筑数据
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select exists (select 1 from house.building_month where year_month = #{endYearMonth})
+""")
+    boolean hasBuildingMonth(@Param("endYearMonth") Integer endYearMonth);
+
+    @Update("""
+insert into house.building_idle_strategy
+(
+year_month,
+building_id,
+first_unit,
+second_unit,
+third_unit,
+site_num,
+site_name,
+address,
+city_level,
+city_region,
+area_sector,
+has_land,
+site_id,
+building_name,
+housing_acquisition_rate,
+housing_source,
+acquisition_date,
+house_year_began,
+investor,
+management_level,
+building_structure,
+total_floors,
+assets_num,
+assets_tag_num,
+usage_status,
+building_use,
+ownership_status,
+floor_area,
+building_area,
+building_area_self_use,
+building_area_rent,
+building_area_idle,
+building_area_unusable,
+usable_area,
+usable_area_self_use,
+usable_area_rent,
+usable_area_idle,
+usable_area_unusable,
+city,
+district,
+lng_wgs84,
+lat_wgs84,
+lng_bd09,
+lat_bd09,
+building_img,
+area_no,
+area_name,
+city_no,
+city_name,
+year_no,
+month_no,
+house_age,
+land_name,
+frontage,
+courtyard,
+whole_building,
+property_ownership_certificate,
+no_property_ownership_certificate_reason,
+unrelated_assets,
+community_assistant_name,
+community_assistant_unit,
+lng_jt,
+lat_jt,
+property_owner,
+checked,
+city_id,
+district_id
+)
+select
+year_month,
+building_id,
+first_unit,
+second_unit,
+third_unit,
+site_num,
+site_name,
+address,
+city_level,
+city_region,
+area_sector,
+has_land,
+site_id,
+building_name,
+housing_acquisition_rate,
+housing_source,
+acquisition_date,
+house_year_began,
+investor,
+management_level,
+building_structure,
+total_floors,
+assets_num,
+assets_tag_num,
+usage_status,
+building_use,
+ownership_status,
+floor_area,
+building_area,
+building_area_self_use,
+building_area_rent,
+building_area_idle,
+building_area_unusable,
+usable_area,
+usable_area_self_use,
+usable_area_rent,
+usable_area_idle,
+usable_area_unusable,
+city,
+district,
+lng_wgs84,
+lat_wgs84,
+lng_bd09,
+lat_bd09,
+building_img,
+area_no,
+area_name,
+city_no,
+city_name,
+year_no,
+month_no,
+house_age,
+land_name,
+frontage,
+courtyard,
+whole_building,
+property_ownership_certificate,
+no_property_ownership_certificate_reason,
+unrelated_assets,
+community_assistant_name,
+community_assistant_unit,
+lng_jt,
+lat_jt,
+property_owner,
+checked,
+city_id,
+district_id
+from house.building_month
+where building_area_idle > 1000
+and year_month = #{endYearMonth}
+order by building_area_idle desc
+""")
+    int insertHouseBuildingIdleStrategy(@Param("endYearMonth") Integer endYearMonth);
+
+    @Update("""
+with
+t101 as (
+select
+    *,
+    row_number() over (order by building_area_idle desc) as sort
+from
+    house.building_idle_strategy
+where
+    year_month = #{endYearMonth}
+),
+t201 as (
+select
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    'kpi_301320_155_01' as kpi_code,
+    '闲置建筑面积' as kpi_name,
+    round(building_area_idle, 2)::varchar as kpi_value,
+    '1' as kpi_type,
+    building_id as jk_object_no,
+    building_name as jk_object,
+    sort
+from t101
+),
+t202 as (
+select
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    'kpi_301320_155_02' as kpi_code,
+    '房产名称' as kpi_name,
+    building_name as kpi_value,
+    '0' as kpi_type,
+    building_id as jk_object_no,
+    building_name as jk_object,
+    sort
+from t101
+),
+t203 as (
+select
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    'kpi_301320_155_03' as kpi_code,
+    '房产编号' as kpi_name,
+    building_id as kpi_value,
+    '0' as kpi_type,
+    building_id as jk_object_no,
+    building_name as jk_object,
+    sort
+from t101
+),
+t204 as (
+select
+    area_no,
+    area_name,
+    city_no,
+    city_name,
+    'kpi_301320_155_04' as kpi_code,
+    '房产总建筑面积' as kpi_name,
+    round(building_area, 2)::varchar as kpi_value,
+    '0' as kpi_type,
+    building_id as jk_object_no,
+    building_name as jk_object,
+    sort
+from t101
+),
+t301 as (
+select * from t201
+union all
+select * from t202
+union all
+select * from t203
+union all
+select * from t204
+)
+insert into publish.house_building_idle_strategy
+(
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+jk_object_no,
+jk_object,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+sort
+)
+select
+#{endYearMonth} as acct_date,
+'301320' as dept_code,
+'河北省分公司纵横运营中心' as dept_name,
+'301320_155' as strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+'' as sale_no,
+'' as sale_name,
+jk_object_no,
+jk_object,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type,
+sort
+from t301 order by sort, kpi_code
+""")
+    int insertPublicBuildingIdleStrategy(@Param("endYearMonth") Integer endYearMonth);
+
+    /**
+     * 查询高油耗车辆策略
+     *
+     * @param endYearMonth 账期
+     */
+    @Select("""
+select
+acct_date,
+dept_code,
+dept_name,
+strategy_code,
+area_no,
+area_name,
+city_no,
+city_name,
+sale_no,
+sale_name,
+jk_object_no,
+jk_object,
+kpi_code,
+kpi_name,
+kpi_value,
+kpi_type
+from publish.house_building_idle_strategy where acct_date = #{endYearMonth} order by sort, kpi_code
+""")
+    List<LinkedHashMap<String, Object>> getBuildingIdleStrategy(@Param("endYearMonth") Integer endYearMonth);
+}

+ 81 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/cxdp/CarCxdpJob.java

@@ -0,0 +1,81 @@
+package com.nokia.finance.tasks.jobs.car.cxdp;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarCxdpDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 车效大屏建设数据定时任务
+ */
+@Slf4j
+@Service
+public class CarCxdpJob {
+    private final JobConfig jobConfig;
+    private final CarCxdpDao carCxdpDao;
+
+    CarCxdpJob(JobConfig jobConfig, CarCxdpDao carCxdpDao) {
+        this.jobConfig = jobConfig;
+        this.carCxdpDao = carCxdpDao;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 14 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行车效大屏建设数据定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            boolean flag = carCxdpDao.hasCarCxdp(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("车效大屏缺少数据");
+            }
+            carCxdpDao.insertCarCxdp(startYearMonth, endYearMonth);
+            List<LinkedHashMap<String, Object>> list = carCxdpDao.getCarCxdp(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getCarCxdpOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarCxdpOutputPath()
+                            + "car_cxdp_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车效大屏建设数据定时任务失败");
+        }
+    }
+}

+ 51 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarBaseDataMonthProcJob.java

@@ -0,0 +1,51 @@
+package com.nokia.finance.tasks.jobs.car.procedure;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.dao.car.CarProcedureDao;
+import com.nokia.finance.tasks.dao.gdc.car.GdcCarProcedureDao;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 车辆基本信息月数据加工定时任务
+ */
+@Slf4j
+@Service
+public class CarBaseDataMonthProcJob {
+    private final CarProcedureDao carProcedureDao;
+    private final GdcCarProcedureDao gdcCarProcedureDao;
+
+    public CarBaseDataMonthProcJob(CarProcedureDao carProcedureDao, GdcCarProcedureDao gdcCarProcedureDao) {
+        this.carProcedureDao = carProcedureDao;
+        this.gdcCarProcedureDao = gdcCarProcedureDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 0 0 3 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        try {
+            log.info("执行车辆基本信息月数据加工定时任务");
+            LocalDate localDateNow = LocalDate.now();
+            LocalDate localDateEnd = localDateNow.minusMonths(1);
+            Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            int update1 = carProcedureDao.insertCarBaseDataMonth(endYearMonth);
+            int update2 = carProcedureDao.updateCarBaseDataMonthChange(endYearMonth);
+            int update3 = gdcCarProcedureDao.insertCarInfo(endYearMonth);
+            gdcCarProcedureDao.insertCarScrap(endYearMonth);
+            if (update1 == 0 || update2 == 0 || update3 == 0) {
+                throw new MyRuntimeException("车辆基本信息月数据加工定时任务失败");
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆基本信息月数据加工定时任务失败");
+        }
+    }
+}

+ 71 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarFeeProcJob.java

@@ -0,0 +1,71 @@
+package com.nokia.finance.tasks.jobs.car.procedure;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.dao.car.CarProcedureDao;
+import com.nokia.finance.tasks.dao.gdc.car.GdcCarProcedureDao;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 车辆费用数据加工定时任务
+ */
+@Slf4j
+@Service
+public class CarFeeProcJob {
+    private final CarProcedureDao carProcedureDao;
+    private final GdcCarProcedureDao gdcCarProcedureDao;
+
+    public CarFeeProcJob(CarProcedureDao carProcedureDao, GdcCarProcedureDao gdcCarProcedureDao) {
+        this.carProcedureDao = carProcedureDao;
+        this.gdcCarProcedureDao = gdcCarProcedureDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 2 0 13 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        try {
+            log.info("执行车辆费用数据加工定时任务");
+            // 当前日期
+            LocalDate localDateNow = LocalDate.now();
+            // 上个月1号
+            LocalDate localDateEnd = localDateNow.minusMonths(1);
+            // 年初1月1号
+            LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+            // 结束年月
+            Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            // 开始年月
+            Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            carProcedureDao.insertCarQiTa(endYearMonth);
+            carProcedureDao.insertCarNianJianFei(endYearMonth);
+            carProcedureDao.insertCarBaoXian(endYearMonth);
+            carProcedureDao.insertCarLuQiao(endYearMonth);
+            carProcedureDao.insertCarWeiXiu(endYearMonth);
+            carProcedureDao.insertCarRanYou(endYearMonth);
+            carProcedureDao.insertCarZuLin(endYearMonth);
+            carProcedureDao.updateCarQiTan(endYearMonth);
+            carProcedureDao.updateCarNianJianFei(endYearMonth);
+            carProcedureDao.updateCarBaoXian(endYearMonth);
+            carProcedureDao.updateCarLuQiao(endYearMonth);
+            carProcedureDao.updateCarWeiXiu(endYearMonth);
+            carProcedureDao.updateCarRanYou(endYearMonth);
+            carProcedureDao.updateCarZuLin(endYearMonth);
+            int update1 = carProcedureDao.updateCarFeiYongMonthYunXingFeiZongFeiYong(endYearMonth);
+            int update2 = carProcedureDao.updateCarFeiYongMonthBaseInfo(endYearMonth);
+            int update3 = gdcCarProcedureDao.insertOneCarOneTable(endYearMonth);
+            if (update1 == 0 || update2 == 0 || update3 == 0) {
+                throw new MyRuntimeException("车辆费用数据加工定时任务失败");
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆费用数据加工定时任务失败");
+        }
+    }
+}

+ 57 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarLiChengMonthProcJob.java

@@ -0,0 +1,57 @@
+package com.nokia.finance.tasks.jobs.car.procedure;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.dao.car.CarProcedureDao;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 车辆行驶里程月数据加工定时任务
+ */
+@Slf4j
+@Service
+public class CarLiChengMonthProcJob {
+    private final CarProcedureDao carProcedureDao;
+
+    public CarLiChengMonthProcJob(CarProcedureDao carProcedureDao) {
+        this.carProcedureDao = carProcedureDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 2 0 3 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        try {
+            log.info("执行车辆行驶里程月数据加工定时任务");
+            // 当前日期
+            LocalDate localDateNow = LocalDate.now();
+            // 上个月1号
+            LocalDate localDateEnd = localDateNow.minusMonths(1);
+            // 年初1月1号
+            LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+            // 结束年月
+            Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            // 开始年月
+            Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            int update1 = carProcedureDao.updateCarLiChengMonthWorkday(endYearMonth);
+            int update2 = carProcedureDao.updateCarLiChengMonthRiJunLiChengChuQinLv(endYearMonth);
+            int update3 = carProcedureDao.updateCarLiChengMonthBaseInfo(endYearMonth);
+            int update4 = carProcedureDao.updateCarLiChengMonthDiXiao(endYearMonth);
+            int update5 = carProcedureDao.insertCarLiChengLeiJiMonth(startYearMonth, endYearMonth);
+            carProcedureDao.insertCarDiXiaoMonth(endYearMonth);
+            if (update1 == 0 || update2 == 0 || update3 == 0 || update4 == 0 || update5 == 0) {
+                throw new MyRuntimeException("车辆行驶里程月数据加工定时任务失败");
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆行驶里程月数据加工定时任务失败");
+        }
+    }
+}

+ 59 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/procedure/CarPaiDanProcJob.java

@@ -0,0 +1,59 @@
+package com.nokia.finance.tasks.jobs.car.procedure;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.dao.car.CarProcedureDao;
+import com.nokia.finance.tasks.dao.gdc.car.GdcCarProcedureDao;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 车辆派单数据加工定时任务
+ */
+@Slf4j
+@Service
+public class CarPaiDanProcJob {
+    private final CarProcedureDao carProcedureDao;
+    private final GdcCarProcedureDao gdcCarProcedureDao;
+
+    public CarPaiDanProcJob(CarProcedureDao carProcedureDao, GdcCarProcedureDao gdcCarProcedureDao) {
+        this.carProcedureDao = carProcedureDao;
+        this.gdcCarProcedureDao = gdcCarProcedureDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 4 0 3 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        try {
+            log.info("执行车辆派单数据加工定时任务");
+            // 当前日期
+            LocalDate localDateNow = LocalDate.now();
+            // 上个月1号
+            LocalDate localDateEnd = localDateNow.minusMonths(1);
+            // 年初1月1号
+            LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+            // 结束年月
+            Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            // 开始年月
+            Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            boolean flag = carProcedureDao.hasCarBaseDataYongChe(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("没有车辆基本信息、用车数据");
+            }
+            carProcedureDao.insertCarWeiGui(endYearMonth);
+            gdcCarProcedureDao.insertCarWeiGui(endYearMonth);
+            gdcCarProcedureDao.insertCarWuDanYongCheBaoJing(endYearMonth);
+            gdcCarProcedureDao.insertCarWuPaiDanYueJieTongJi(startYearMonth, endYearMonth);
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆派单数据加工定时任务失败");
+        }
+    }
+}

+ 398 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/ruixing/CarYongCheZongLanJob.java

@@ -0,0 +1,398 @@
+//package com.nokia.finance.tasks.jobs.car.ruixing;
+//
+//import com.google.gson.Gson;
+//import com.google.gson.reflect.TypeToken;
+//import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+//import com.nokia.finance.tasks.common.utils.psql.PsqlUtil;
+//import com.nokia.finance.tasks.config.JobConfig;
+//import com.nokia.finance.tasks.pojo.po.common.AreaPo;
+//import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+//import com.nokia.finance.tasks.service.car.CarService;
+//import com.nokia.finance.tasks.service.common.AreaService;
+//import com.nokia.finance.tasks.service.common.OrganizationService;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.csv.CSVFormat;
+//import org.apache.commons.csv.CSVPrinter;
+//import org.apache.poi.ss.usermodel.Cell;
+//import org.apache.poi.ss.usermodel.DateUtil;
+//import org.apache.poi.ss.usermodel.Row;
+//import org.apache.poi.ss.usermodel.Sheet;
+//import org.apache.poi.ss.usermodel.Workbook;
+//import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+//import org.springframework.stereotype.Service;
+//import org.springframework.util.CollectionUtils;
+//
+//import java.io.InputStream;
+//import java.io.OutputStreamWriter;
+//import java.nio.charset.StandardCharsets;
+//import java.nio.file.Files;
+//import java.nio.file.Path;
+//import java.nio.file.Paths;
+//import java.nio.file.StandardCopyOption;
+//import java.time.LocalDate;
+//import java.time.format.DateTimeFormatter;
+//import java.util.ArrayList;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.concurrent.CompletableFuture;
+//import java.util.concurrent.TimeUnit;
+//import java.util.regex.Matcher;
+//import java.util.regex.Pattern;
+//import java.util.stream.Stream;
+//
+///**
+// * 睿行车辆用车信息总览月数据入库定时任务
+// */
+//@Slf4j
+//@Service
+//public class CarYongCheZongLanJob {
+//    private final JobConfig jobConfig;
+//    private final CarService carService;
+//    private final OrganizationService organizationService;
+//    private final AreaService areaService;
+//
+//    public CarYongCheZongLanJob(JobConfig jobConfig, CarService carService, OrganizationService organizationService,
+//                                AreaService areaService) {
+//        this.jobConfig = jobConfig;
+//        this.carService = carService;
+//        this.organizationService = organizationService;
+//        this.areaService = areaService;
+//    }
+//
+//    /**
+//     * 执行任务
+//     */
+////    @Scheduled(cron = "0 58 5 1 * ?")
+//    public void runJob() {
+//        // 数据目录
+//        Path dir = Paths.get(jobConfig.getCarYongCheZongLanSourcePath());
+//        try (Stream<Path> stream = Files.list(dir)) {
+//            // 获取数据目录下的文件列表
+//            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+//            log.info("睿行车辆用车信息总览月数据文件列表: {}", pathList);
+//            if (CollectionUtils.isEmpty(pathList)) {
+//                throw new MyRuntimeException("睿行车辆用车信息总览月数据没有文件");
+//            }
+//            for (Path path : pathList) {
+//                CompletableFuture.runAsync(() -> {
+//                    try {
+//                        singleJob(path);
+//                    } catch (Exception e) {
+//                        throw new MyRuntimeException(e);
+//                    }
+//                }).get(5, TimeUnit.MINUTES);
+//            }
+//        } catch (InterruptedException e) {
+//            log.error("线程中断: {}", e.getMessage(), e);
+//            Thread.currentThread().interrupt();
+//        } catch (Exception e) {
+//            log.error(e.getMessage(), e);
+//        }
+//    }
+//
+//    /**
+//     * 处理单个文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public void singleJob(Path path) throws Exception {
+//        if (Files.size(path) == 0) {
+//            move(path);
+//            throw new MyRuntimeException(path.getFileName() + " 空文件");
+//        }
+//        List<Map<String, String>> list = readFile(path);
+////        List<Map<String, String>> distinctList = dataProcessing(path, list);
+////        Path csvPath = toCsv(path, distinctList);
+//        Path csvPath = toCsv(path, list);
+////        copyCsv(csvPath);
+////        move(path);
+//    }
+//
+//    /**
+//     * 读取文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public List<Map<String, String>> readFile(Path path) throws Exception {
+//        log.info("读取: {}", path);
+//        try (InputStream inputStream = Files.newInputStream(path);
+//             Workbook workbook = new XSSFWorkbook(inputStream)
+//        ) {
+//            List<Map<String, String>> resultList = new ArrayList<>();
+//            // 读取第一个工作表
+//            Sheet sheet = workbook.getSheetAt(0);
+//            // 最后行数
+//            int lastRowNum = sheet.getLastRowNum();
+//            log.info("lastRowNum: {}", lastRowNum);
+//            if (lastRowNum == 0) {
+//                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+//            }
+//            Gson gson = new Gson();
+//            int currentRowNum = 0;
+//            while (currentRowNum <= lastRowNum) {
+//                log.info(">>>>>>>>>>currentRowNum: {}", currentRowNum);
+//                Map<String, String> rowMap = new LinkedHashMap<>();
+//                // 申请单表头行
+//                Row row1 = sheet.getRow(currentRowNum);
+//                // 申请单数据行
+//                Row row2 = sheet.getRow(++currentRowNum);
+//                if (currentRowNum > lastRowNum) {
+//                    break;
+//                }
+//                List<String> headers1;
+//                int lastCellNum1 = row1.getLastCellNum();
+//                headers1 = switch (lastCellNum1) {
+//                    case 9 ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_qing_shi_jian").toList();
+//                    case 13 ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_qing_shi_jian").toList();
+//                    case 17 ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_pi_ren2", "shen_pi_jie_guo2", "shen_pi_shi_jian2", "shen_pi_yi_jian2", "shen_qing_shi_jian").toList();
+//                    default ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_pi_ren2", "shen_pi_jie_guo2", "shen_pi_shi_jian2", "shen_pi_yi_jian2", "shen_pi_ren3", "shen_pi_jie_guo3", "shen_pi_shi_jian3", "shen_pi_yi_jian3", "shen_qing_shi_jian").toList();
+//                };
+//
+//                int headerSize1 = headers1.size();
+//                for (int i = 0; i < headerSize1; i++) {
+//                    String header = headers1.get(i);
+//                    Cell cell = row2.getCell(i);
+//                    String cellValue = "";
+//                    switch (cell.getCellType()) {
+//                        case STRING:
+//                            boolean skipTrim = "shen_qing_shi_jian".equals(header)
+//                                    || "shen_pi_shi_jian1".equals(header)
+//                                    || "shen_pi_shi_jian2".equals(header)
+//                                    || "shen_pi_shi_jian3".equals(header);
+//                            // 删除字符串空白字符
+//                            cellValue = skipTrim ? cell.getStringCellValue()
+//                                    : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+//                            break;
+//                        case NUMERIC:
+//                            if (DateUtil.isCellDateFormatted(cell)) {
+//                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+//                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+//                                break;
+//                            }
+//                            cellValue = String.valueOf(cell.getNumericCellValue());
+//                            break;
+//                        case BOOLEAN:
+//                            cellValue = String.valueOf(cell.getBooleanCellValue());
+//                            break;
+//                        default:
+//                            break;
+//                    }
+//                    rowMap.put(header, cellValue);
+//                }
+//                ++currentRowNum;
+//                if (currentRowNum > lastRowNum) {
+//                    resultList.add(rowMap);
+//                    break;
+//                }
+//                if (!"派遣单编号".equals(sheet.getRow(currentRowNum).getCell(0).getStringCellValue())) {
+//                    resultList.add(rowMap);
+//                    continue;
+//                }
+//
+//                while (currentRowNum <= lastRowNum) {
+//                    Map<String, String> rowMapCopy = gson.fromJson(gson.toJson(rowMap), new TypeToken<>() {});
+//                    // 派遣单表头行
+//                    Row row3 = sheet.getRow(currentRowNum);
+//                    if (!"派遣单编号".equals(row3.getCell(0).getStringCellValue())) {
+//                        break;
+//                    }
+//                    Row row4 = sheet.getRow(++currentRowNum);
+//                    if (currentRowNum > lastRowNum) {
+//                        break;
+//                    }
+//                    List<String> headers2 = Stream.of("pai_qian_dan_bian_hao", "che_pai_hao", "jia_shi_yuan", "chu_che_shi_jian", "gui_dui_shi_jian", "pai_qian_che_liang_zhuang_tai", "ren_wu_zhi_xing_zhuang_tai").toList();
+//                    int headersSize2 = headers2.size();
+//                    for (int i = 0; i < headersSize2; i++) {
+//                        String header = headers2.get(i);
+//                        Cell cell = row4.getCell(i);
+//                        String cellValue = "";
+//                        switch (cell.getCellType()) {
+//                            case STRING:
+//                                boolean skipTrim = "chu_che_shi_jian".equals(header)
+//                                        || "gui_dui_shi_jian".equals(header);
+//                                // 删除字符串空白字符
+//                                cellValue = skipTrim ? cell.getStringCellValue()
+//                                        : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+//                                break;
+//                            case NUMERIC:
+//                                if (DateUtil.isCellDateFormatted(cell)) {
+//                                    cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+//                                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+//                                    break;
+//                                }
+//                                cellValue = String.valueOf(cell.getNumericCellValue());
+//                                break;
+//                            case BOOLEAN:
+//                                cellValue = String.valueOf(cell.getBooleanCellValue());
+//                                break;
+//                            default:
+//                                break;
+//                        }
+//                        rowMapCopy.put(header, cellValue);
+//                    }
+//                    resultList.add(rowMapCopy);
+//                    currentRowNum++;
+//                }
+//            }
+//            return resultList;
+//        }
+//    }
+//
+//    /**
+//     * 数据加工
+//     *
+//     * @param path 文件路径
+//     * @param list 数据
+//     */
+//    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+//        // 从文件名提取日期
+//        String regex = "\\d{6}";
+//        Pattern pattern = Pattern.compile(regex);
+//        Matcher matcher = pattern.matcher(path.getFileName().toString());
+//        String dateString;
+//        if (matcher.find()) {
+//            dateString = matcher.group() + "01";
+//        } else {
+//            throw new MyRuntimeException(path.getFileName() + " 提取日期失败");
+//        }
+//        LocalDate localDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
+//        String yearMonth = localDate.format(DateTimeFormatter.ofPattern("yyyyMM"));
+//        String year = String.valueOf(localDate.getYear());
+//        String month = String.valueOf(localDate.getMonthValue());
+//        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+//        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+//        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+//        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+//                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+//        List<AreaPo> cities = areaService.getCities();
+//        List<AreaPo> districts = areaService.getDistricts();
+//        Map<String, AreaPo> areaMap = areaService.getAreaMap(cities, districts);
+//        Map<String, List<AreaPo>> districtListMap = areaService.getDistrictListMap(cities, districts);
+//        for (Map<String, String> map : list) {
+//            map.put("year_month", yearMonth);
+//            map.put("year_no", year);
+//            map.put("month_no", month);
+//            String rawChePaiHao = map.get("che_pai_hao");
+//            map.put("raw_che_pai_hao", rawChePaiHao);
+//            String chePaiHao = carService.getChePai(rawChePaiHao);
+//            map.put("che_pai_hao", chePaiHao);
+//            String chePaiFail = carService.chePaiFail(rawChePaiHao);
+//            map.put("che_pai_fail", chePaiFail);
+//            String yongCheBuMen = map.get("yong_che_bu_men");
+//            String firstUnit = carService.getFirstUnit(yongCheBuMen);
+//            map.put("first_unit", firstUnit);
+//            String secondUnit = carService.getSecondUnit(yongCheBuMen, firstUnit);
+//            map.put("second_unit", secondUnit);
+//            String thirdUnit = carService.getThirdUnit(yongCheBuMen, secondUnit);
+//            map.put("third_unit", thirdUnit);
+//            String areaNo = carService.getAreaNo(secondOrgs, yongCheBuMen);
+//            map.put("area_no", areaNo);
+//            String areaName = carService.getOrgName(orgMap, areaNo);
+//            map.put("area_name", areaName);
+//            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, yongCheBuMen);
+//            map.put("city_no", cityNo);
+//            String cityName = carService.getOrgName(orgMap, cityNo);
+//            map.put("city_name", cityName);
+//            String areaNo2 = carService.getAreaNo2(areaName, cityName);
+//            map.put("area_no2", areaNo2);
+//            String areaName2 = carService.getOrgName(orgMap, areaNo2);
+//            map.put("area_name2", areaName2);
+//            String cityId = carService.getCityId(cities, yongCheBuMen);
+//            map.put("city_id", cityId);
+//            String city = carService.getAreaName(areaMap, cityId);
+//            map.put("city", city);
+//            String districtId = carService.getDistrictId(districtListMap, cityId, cityName, yongCheBuMen);
+//            map.put("district_id", districtId);
+//            String district = carService.getAreaName(areaMap, districtId);
+//            map.put("district", district);
+//            String baoFei = carService.baoFei(rawChePaiHao);
+//            map.put("bao_fei", baoFei);
+//            map.put("source", path.getFileName().toString());
+//        }
+//        return list;
+//    }
+//
+//    /**
+//     * 生成csv
+//     *
+//     * @param path 源文件路径
+//     * @param list 数据
+//     */
+//    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+//        log.info("条数:{}", list.size());
+//        Files.createDirectories(Paths.get(jobConfig.getCarYongCheZongLanHistoryPath()));
+//        Path csvPath = Paths.get(jobConfig.getCarYongCheZongLanHistoryPath() + path.getFileName() + ".csv");
+//        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+//                StandardCharsets.UTF_8);
+//             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+//            // 添加bom头避免excel乱码
+//            osw.write('\ufeff');
+//            // 表头
+////            printer.printRecord("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_qing_shi_jian", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_pi_ren2", "shen_pi_jie_guo2", "shen_pi_shi_jian2", "shen_pi_yi_jian2", "shen_pi_ren3", "shen_pi_jie_guo3", "shen_pi_shi_jian3", "shen_pi_yi_jian3", "pai_qian_dan_bian_hao", "che_pai_hao", "jia_shi_yuan", "chu_che_shi_jian", "gui_dui_shi_jian", "pai_qian_che_liang_zhuang_tai", "ren_wu_zhi_xing_zhuang_tai");
+//            printer.printRecord("申请单号","申请人","申请人单位","申请类型","用车人","用车人单位","用车事由","申请单状态","申请时间","审批人1","审批结果1","审批时间1","审批意见1","审批人2","审批结果2","审批时间2","审批意见2","审批人3","审批结果3","审批时间3","审批意见3","派遣单编号","车牌号码","驾驶员","出车时间","归队时间","派遣车辆状态","任务执行状态");
+//            for (Map<String, String> map : list) {
+//                printer.printRecord(
+//                        map.get("shen_qing_dan_hao"),
+//                        map.get("shen_qing_ren"),
+//                        map.get("shen_qing_ren_dan_wei"),
+//                        map.get("shen_qing_lei_xing"),
+//                        map.get("yong_che_ren"),
+//                        map.get("yong_che_ren_dan_wei"),
+//                        map.get("yong_che_shi_you"),
+//                        map.get("shen_qing_dan_zhuang_tai"),
+//                        map.get("shen_qing_shi_jian"),
+//                        map.get("shen_pi_ren1"),
+//                        map.get("shen_pi_jie_guo1"),
+//                        map.get("shen_pi_shi_jian1"),
+//                        map.get("shen_pi_yi_jian1"),
+//                        map.get("shen_pi_ren2"),
+//                        map.get("shen_pi_jie_guo2"),
+//                        map.get("shen_pi_shi_jian2"),
+//                        map.get("shen_pi_yi_jian2"),
+//                        map.get("shen_pi_ren3"),
+//                        map.get("shen_pi_jie_guo3"),
+//                        map.get("shen_pi_shi_jian3"),
+//                        map.get("shen_pi_yi_jian3"),
+//                        map.get("pai_qian_dan_bian_hao"),
+//                        map.get("che_pai_hao"),
+//                        map.get("jia_shi_yuan"),
+//                        map.get("chu_che_shi_jian"),
+//                        map.get("gui_dui_shi_jian"),
+//                        map.get("pai_qian_che_liang_zhuang_tai"),
+//                        map.get("ren_wu_zhi_xing_zhuang_tai")
+//                );
+//            }
+//        }
+//        return csvPath;
+//    }
+//
+//    /**
+//     * 导入数据库
+//     *
+//     * @param path 文件路径
+//     */
+//    public void copyCsv(Path path) {
+//        String dbTable = "car.car_yong_che_zong_lan";
+//        String csv = path.toString();
+//        String columns = "(shen_qing_dan_hao,pai_qian_dan_hao,shen_qing_lei_xing,che_pai_hao,che_liang_lei_xing,che_liang_ji_bie,si_ji_ming_cheng,yong_che_ren,yong_che_bu_men,yong_che_shi_you,chu_fa_di,mu_di_di,chu_fa_shi_jian,gui_dui_shi_jian,xing_shi_li_cheng,chu_che_shi_chang,year_month,year_no,month_no,raw_che_pai_hao,che_pai_fail,first_unit,second_unit,third_unit,area_no,area_name,city_no,city_name,area_no2,area_name2,city_id,city,district_id,district,bao_fei,source)";
+//        Long timeout = 60000L;
+//        PsqlUtil.copyCsv(jobConfig.getCopyScriptPath(), jobConfig.getDbHost(), jobConfig.getDbPort(),
+//                jobConfig.getDbUsername(), jobConfig.getDbPassword(), jobConfig.getDbName(), dbTable, csv, columns,
+//                timeout, null);
+//    }
+//
+//    /**
+//     * 移动源文件到历史文件夹
+//     *
+//     * @param path 源文件路径
+//     */
+//    public void move(Path path) throws Exception {
+//        Path targetPath = Paths.get(jobConfig.getCarYongCheZongLanHistoryPath(), path.getFileName().toString());
+//        Files.move(path, targetPath, StandardCopyOption.REPLACE_EXISTING);
+//    }
+//}

+ 80 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarHighFuelConsumptionJob.java

@@ -0,0 +1,80 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * 高油耗车辆策略定时任务
+ */
+@Slf4j
+@Service
+public class CarHighFuelConsumptionJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarHighFuelConsumptionJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 8 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行高油耗车辆策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            int updateCount = carStrategyDao.insertCarHighFuelConsumption(startYearMonth, endYearMonth);
+            if (updateCount == 0) {
+                throw new MyRuntimeException("插入高油耗车辆策略失败");
+            }
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarHighFuelConsumption(endYearMonth);
+            if (CollectionUtils.isEmpty(list)) {
+                throw new MyRuntimeException("高油耗车辆策略为空");
+            }
+            Files.createDirectories(Paths.get(jobConfig.getCarHighFuelConsumptionOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarHighFuelConsumptionOutputPath()
+                            + "car_high_fuel_consumption_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                LinkedHashMap<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (LinkedHashMap<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("高油耗车辆策略定时任务失败");
+        }
+    }
+}

+ 79 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarHighRepairJob.java

@@ -0,0 +1,79 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * 高修理车辆策略定时任务
+ */
+@Slf4j
+@Service
+public class CarHighRepairJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarHighRepairJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 6 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行高修理车辆策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            int updateCount = carStrategyDao.insertCarHighRepair(startYearMonth, endYearMonth);
+            if (updateCount == 0) {
+                throw new MyRuntimeException("插入高修理车辆策略失败");
+            }
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarHighRepair(endYearMonth);
+            if (CollectionUtils.isEmpty(list)) {
+                throw new MyRuntimeException("高修理车辆策略为空");
+            }
+            Files.createDirectories(Paths.get(jobConfig.getCarHighRepairOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarHighRepairOutputPath()
+                            + "car_high_repair_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                LinkedHashMap<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (LinkedHashMap<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("高修理车辆策略定时任务失败");
+        }
+    }
+}

+ 79 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarInefficiencyPercentJob.java

@@ -0,0 +1,79 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 车辆低效占比策略定时任务
+ */
+@Slf4j
+@Service
+public class CarInefficiencyPercentJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarInefficiencyPercentJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 12 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行车辆低效占比策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            boolean flag = carStrategyDao.hasCarInefficiency(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("车辆低效占比策略缺少数据");
+            }
+            carStrategyDao.insertCarInefficiencyPercent(endYearMonth);
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarInefficiencyPercent(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getCarInefficiencyPercentOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarInefficiencyPercentOutputPath()
+                            + "car_inefficiency_percent_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆低效占比策略定时任务失败");
+        }
+    }
+}

+ 79 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarInefficiencyQxJob.java

@@ -0,0 +1,79 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 车辆低效区县策略定时任务
+ */
+@Slf4j
+@Service
+public class CarInefficiencyQxJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarInefficiencyQxJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 10 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行车辆低效区县策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            boolean flag = carStrategyDao.hasCarInefficiency(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("车辆低效区县策略缺少数据");
+            }
+            carStrategyDao.insertCarInefficiencyQx(endYearMonth);
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarInefficiencyQx(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getCarInefficiencyQxOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarInefficiencyQxOutputPath()
+                            + "car_inefficiency_qx_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆低效区县策略定时任务失败");
+        }
+    }
+}

+ 81 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarRentalRepairJob.java

@@ -0,0 +1,81 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 租赁车辆产生维修费策略定时任务
+ */
+@Slf4j
+@Service
+public class CarRentalRepairJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarRentalRepairJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 4 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行租赁车辆产生维修费策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            boolean flag = carStrategyDao.hasCarRentalRepair(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("租赁车辆产生维修费策略缺少数据");
+            }
+            carStrategyDao.insertCarRentalRepair(startYearMonth, endYearMonth);
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarRentalRepair(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getCarRentalRepairOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarRentalRepairOutputPath()
+                            + "car_rental_repair_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("租赁车辆产生维修费策略定时任务失败");
+        }
+    }
+}

+ 80 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarViolationUnprocessedJob.java

@@ -0,0 +1,80 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 车辆违章未处理策略定时任务
+ */
+@Slf4j
+@Service
+public class CarViolationUnprocessedJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarViolationUnprocessedJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 2 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行车辆违章未处理策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            boolean flag = carStrategyDao.hasCarViolationUnprocessed(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("车辆违章未处理策略缺少数据");
+            }
+            carStrategyDao.insertCarViolationUnprocessed(endYearMonth);
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarViolationUnprocessed(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getCarViolationUnprocessedOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarViolationUnprocessedOutputPath()
+                            + "car_violation_unprocessed_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("车辆违章未处理策略定时任务失败");
+        }
+    }
+}

+ 76 - 0
src/main/java/com/nokia/finance/tasks/jobs/car/strategy/CarWdyjJob.java

@@ -0,0 +1,76 @@
+package com.nokia.finance.tasks.jobs.car.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.car.CarStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 违规车辆策略定时任务
+ */
+@Slf4j
+@Service
+public class CarWdyjJob {
+    private final JobConfig jobConfig;
+    private final CarStrategyDao carStrategyDao;
+
+    CarWdyjJob(JobConfig jobConfig, CarStrategyDao carStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.carStrategyDao = carStrategyDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 0 0 15 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行违规车辆策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            carStrategyDao.insertCarWdyj(endYearMonth);
+            List<LinkedHashMap<String, Object>> list = carStrategyDao.getCarWdyj(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getCarWdyjOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getCarWdyjOutputPath()
+                            + "car_wdyj_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("违规车辆策略定时任务失败");
+        }
+    }
+}

+ 79 - 0
src/main/java/com/nokia/finance/tasks/jobs/house/fcdp/HouseBuildingAreaStatJob.java

@@ -0,0 +1,79 @@
+package com.nokia.finance.tasks.jobs.house.fcdp;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.house.HouseFcdpDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 房产大屏建筑面积统计定时任务
+ */
+@Slf4j
+@Service
+public class HouseBuildingAreaStatJob {
+    private final JobConfig jobConfig;
+    private final HouseFcdpDao houseFcdpDao;
+
+    HouseBuildingAreaStatJob(JobConfig jobConfig, HouseFcdpDao houseFcdpDao) {
+        this.jobConfig = jobConfig;
+        this.houseFcdpDao = houseFcdpDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 0 0 10 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行房产大屏建筑面积统计定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            int update1 = houseFcdpDao.insertHouseBuildingAreaStat(endYearMonth);
+            if (update1 == 0) {
+                throw new MyRuntimeException("房产大屏建筑面积统计定时任务失败");
+            }
+            List<LinkedHashMap<String, Object>> list = houseFcdpDao.getHouseBuildingAreaStat(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getHouseBuildingAreaStatOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getHouseBuildingAreaStatOutputPath()
+                            + "building_area_stat_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("房产大屏建筑面积统计定时任务失败");
+        }
+    }
+}

+ 78 - 0
src/main/java/com/nokia/finance/tasks/jobs/house/fcdp/HouseBuildingLandCountJob.java

@@ -0,0 +1,78 @@
+package com.nokia.finance.tasks.jobs.house.fcdp;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.house.HouseFcdpDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 房产大屏建筑和土地数量统计定时任务
+ */
+@Slf4j
+@Service
+public class HouseBuildingLandCountJob {
+    private final JobConfig jobConfig;
+    private final HouseFcdpDao houseFcdpDao;
+
+    HouseBuildingLandCountJob(JobConfig jobConfig, HouseFcdpDao houseFcdpDao) {
+        this.jobConfig = jobConfig;
+        this.houseFcdpDao = houseFcdpDao;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 2 0 10 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行房产大屏建筑和土地数量统计定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            int update1 = houseFcdpDao.insertHouseBuildingLandCount(endYearMonth);
+            if (update1 == 0) {
+                throw new MyRuntimeException("房产大屏建筑和土地数量统计定时任务失败");
+            }
+            List<LinkedHashMap<String, Object>> list = houseFcdpDao.getHouseBuildingLandCount(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getHouseBuildingLandCountOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getHouseBuildingLandCountOutputPath()
+                            + "building_land_count_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("房产大屏建筑和土地数量统计定时任务失败");
+        }
+    }
+}

+ 69 - 0
src/main/java/com/nokia/finance/tasks/jobs/house/fcdp/HouseRentalIncomeJob.java

@@ -0,0 +1,69 @@
+package com.nokia.finance.tasks.jobs.house.fcdp;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 房产大屏出租收入统计定时任务
+ */
+@Slf4j
+@Service
+public class HouseRentalIncomeJob {
+    private final JobConfig jobConfig;
+
+    HouseRentalIncomeJob(JobConfig jobConfig) {
+        this.jobConfig = jobConfig;
+    }
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 4 0 10 * ?")
+//    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        try {
+            log.info("执行房产大屏出租收入统计定时任务");
+            LocalDate localDateNow = LocalDate.now();
+            LocalDate localDateEnd = localDateNow.minusMonths(1);
+            Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            List<Map<String, Object>> list = new ArrayList<>();
+            Files.createDirectories(Paths.get(jobConfig.getHouseRentalIncomeOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getHouseRentalIncomeOutputPath()
+                            + "rental_income_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            throw new MyRuntimeException("执行房产大屏出租收入统计定时任务失败");
+        }
+    }
+}

+ 55 - 0
src/main/java/com/nokia/finance/tasks/jobs/house/procedure/HouseBuildingRepairProcJob.java

@@ -0,0 +1,55 @@
+package com.nokia.finance.tasks.jobs.house.procedure;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.dao.house.HouseProcedureDao;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 不动产自有房产维修数据加工定时任务
+ */
+@Slf4j
+@Service
+public class HouseBuildingRepairProcJob {
+    private final HouseProcedureDao houseProcedureDao;
+
+    public HouseBuildingRepairProcJob(HouseProcedureDao houseProcedureDao) {
+        this.houseProcedureDao = houseProcedureDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 0 0 13 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        try {
+            log.info("执行不动产自有房产维修数据加工定时任务");
+            // 当前日期
+            LocalDate localDateNow = LocalDate.now();
+            // 上个月1号
+            LocalDate localDateEnd = localDateNow.minusMonths(1);
+            // 年初1月1号
+            LocalDate localDateStart = localDateEnd.withDayOfYear(1);
+            // 结束年月
+            Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            // 开始年月
+            Integer startYearMonth = Integer.valueOf(localDateStart.format(DateTimeFormatter.ofPattern("yyyyMM")));
+            int update1 = houseProcedureDao.insertBuildingSameRepairFrequency(startYearMonth, endYearMonth);
+            int update2 = houseProcedureDao.insertBuildingHighRepair(startYearMonth, endYearMonth);
+            int update3 = houseProcedureDao.insertBuildingHighSporadicRepair(startYearMonth, endYearMonth);
+            houseProcedureDao.insertBuildingIdleRepair(endYearMonth);
+            if (update1 == 0 || update2 == 0 || update3 == 0) {
+                throw new MyRuntimeException("不动产自有房产维修数据加工定时任务失败");
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("不动产自有房产维修数据加工定时任务失败");
+        }
+    }
+}

+ 81 - 0
src/main/java/com/nokia/finance/tasks/jobs/house/strategy/HouseBuildingIdleStrategyJob.java

@@ -0,0 +1,81 @@
+package com.nokia.finance.tasks.jobs.house.strategy;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.config.JobConfig;
+import com.nokia.finance.tasks.dao.house.HouseStrategyDao;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 闲置建筑面积超过1000平米策略定时任务
+ */
+@Slf4j
+@Service
+public class HouseBuildingIdleStrategyJob {
+    private final JobConfig jobConfig;
+    private final HouseStrategyDao houseStrategyDao;
+
+    HouseBuildingIdleStrategyJob(JobConfig jobConfig, HouseStrategyDao houseStrategyDao) {
+        this.jobConfig = jobConfig;
+        this.houseStrategyDao = houseStrategyDao;
+    }
+
+    /**
+     * 执行任务
+     */
+    @Scheduled(cron = "0 6 0 10 * ?")
+    @Transactional(timeout = 60, rollbackFor = Exception.class)
+    public void runJob() {
+        log.info("执行闲置建筑面积超过1000平米策略定时任务");
+        LocalDate localDateNow = LocalDate.now();
+        LocalDate localDateEnd = localDateNow.minusMonths(1);
+        Integer endYearMonth = Integer.valueOf(localDateEnd.format(DateTimeFormatter.ofPattern("yyyyMM")));
+        try {
+            boolean flag = houseStrategyDao.hasBuildingMonth(endYearMonth);
+            if (!flag) {
+                throw new MyRuntimeException("闲置建筑面积超过1000平米策略缺少数据");
+            }
+            houseStrategyDao.insertHouseBuildingIdleStrategy(endYearMonth);
+            houseStrategyDao.insertPublicBuildingIdleStrategy(endYearMonth);
+            List<LinkedHashMap<String, Object>> list = houseStrategyDao.getBuildingIdleStrategy(endYearMonth);
+            Files.createDirectories(Paths.get(jobConfig.getHouseBuildingIdleStrategyOutputPath()));
+            char delimiter = 1;
+            try (OutputStreamWriter osw = new OutputStreamWriter(
+                    Files.newOutputStream(Paths.get(jobConfig.getHouseBuildingIdleStrategyOutputPath()
+                            + "building_idle_strategy_" + endYearMonth + ".csv")),
+                    StandardCharsets.UTF_8);
+                 CSVPrinter printer = new CSVPrinter(osw,
+                         CSVFormat.DEFAULT.builder().setDelimiter(delimiter).build())) {
+                if (CollectionUtils.isEmpty(list)) {
+                    return;
+                }
+                // 添加bom头避免excel乱码
+                osw.write('\ufeff');
+                Map<String, Object> header = list.get(0);
+                // 表头
+                printer.printRecord(header.keySet());
+                for (Map<String, Object> map : list) {
+                    printer.printRecord(map.values());
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new MyRuntimeException("闲置建筑面积超过1000平米策略定时任务失败");
+        }
+    }
+}

+ 16 - 0
src/main/java/com/nokia/finance/tasks/service/car/CarService.java

@@ -161,6 +161,14 @@ public class CarService {
                 return "廊坊开发区";
             }
         }
+        if ("邢台".equals(firstUnit)) {
+            if (unit.contains("内丘")) {
+                return "内邱";
+            }
+            if (unit.contains("任泽")) {
+                return "任县";
+            }
+        }
         if ("唐山".equals(firstUnit)) {
             if (unit.contains("高开区")) {
                 return "唐山高开区";
@@ -275,6 +283,14 @@ public class CarService {
                 return "D0130406";
             }
         }
+        if ("邢台".equals(areaName)) {
+            if (unit.contains("内丘")) {
+                return "D0130523";
+            }
+            if (unit.contains("任泽")) {
+                return "D0130526";
+            }
+        }
         if ("省机动局".equals(areaName)) {
             if (unit.contains("沧州")) {
                 return "HECS180";

+ 44 - 0
src/main/java/com/nokia/finance/tasks/utils/PinYinUtil.java

@@ -0,0 +1,44 @@
+//package com.nokia.finance.tasks.utils;
+//
+//import lombok.extern.slf4j.Slf4j;
+//import net.sourceforge.pinyin4j.PinyinHelper;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
+//import org.springframework.util.StringUtils;
+//
+//@Slf4j
+//public class PinYinUtil {
+//    /**
+//     * 汉字转拼音
+//     */
+//    public static String convert(String str) {
+//        if (!StringUtils.hasText(str)) {
+//            return "";
+//        }
+//        char[] chars = str.toCharArray();
+//        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
+//        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
+//        format.setVCharType(HanyuPinyinVCharType.WITH_V);
+//        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
+//        StringBuilder sb = new StringBuilder();
+//        for (char c : chars) {
+//            if (Character.toString(c).matches("[\\u4e00-\\u9fa5]+")) {
+//                try {
+//                    String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
+//                    if (pinyinArray != null && pinyinArray.length > 0) {
+//                        sb.append(pinyinArray[0]);
+//                        sb.append(" ");
+//                    } else {
+//                        sb.append(c);
+//                        sb.append(" ");
+//                    }
+//                } catch (Exception e) {
+//                    log.info(e.getMessage(), e);
+//                }
+//            }
+//        }
+//        return sb.toString();
+//    }
+//}

+ 42 - 0
src/test/java/com/nokia/finance/tasks/HanZiToPinYinTest.java

@@ -0,0 +1,42 @@
+//package com.nokia.finance.tasks;
+//
+//import lombok.extern.slf4j.Slf4j;
+//import net.sourceforge.pinyin4j.PinyinHelper;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
+//import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
+//
+//@Slf4j
+//class HanZiToPinYinTest {
+//    public static void main(String[] args) {
+//        String chineseText = "女人";
+//        char[] chars = chineseText.toCharArray();
+//        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
+//        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
+//        format.setVCharType(HanyuPinyinVCharType.WITH_V);
+//        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
+//        StringBuilder sb = new StringBuilder();
+//        for (char c : chars) {
+//            if (Character.toString(c).matches("[\\u4e00-\\u9fa5]+")) {
+//                try {
+//                    // 将单个汉字转换为拼音并添加到字符串构建器中
+//                    String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c, format);
+//                    if (pinyinArray != null && pinyinArray.length > 0) {
+//                        sb.append(pinyinArray[0]);
+//                        sb.append(" ");
+//                    } else {
+//                        // 如果某个字符无法转换,则保持原样
+//                        sb.append(c);
+//                        sb.append(" ");
+//                    }
+//                } catch (Exception e) {
+//                    log.info(e.getMessage(), e);
+//                }
+//            }
+//        }
+//
+//        String resultWithoutTones = sb.toString();
+//        System.out.println(resultWithoutTones);
+//    }
+//}

+ 329 - 0
src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests.java

@@ -0,0 +1,329 @@
+//package com.nokia.finance.tasks.car;
+//
+//import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+//import com.nokia.finance.tasks.dao.car.CarGongCheShouFeiDao;
+//import com.nokia.finance.tasks.pojo.po.common.AreaPo;
+//import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+//import com.nokia.finance.tasks.service.car.CarService;
+//import com.nokia.finance.tasks.service.common.AreaService;
+//import com.nokia.finance.tasks.service.common.OrganizationService;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.csv.CSVFormat;
+//import org.apache.commons.csv.CSVPrinter;
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.poi.ss.usermodel.Cell;
+//import org.apache.poi.ss.usermodel.DateUtil;
+//import org.apache.poi.ss.usermodel.Row;
+//import org.apache.poi.ss.usermodel.Sheet;
+//import org.apache.poi.ss.usermodel.Workbook;
+//import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+//import org.junit.jupiter.api.Test;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//import org.springframework.test.context.ActiveProfiles;
+//import org.springframework.util.CollectionUtils;
+//
+//import java.io.InputStream;
+//import java.io.OutputStreamWriter;
+//import java.math.BigDecimal;
+//import java.nio.charset.StandardCharsets;
+//import java.nio.file.Files;
+//import java.nio.file.Path;
+//import java.nio.file.Paths;
+//import java.time.LocalDate;
+//import java.time.LocalDateTime;
+//import java.time.format.DateTimeFormatter;
+//import java.util.ArrayList;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Objects;
+//import java.util.Set;
+//import java.util.stream.Stream;
+//
+//@Slf4j
+//@SpringBootTest
+//@ActiveProfiles("dev")
+//class CarGongCheShiYongTests {
+//    @Autowired
+//    CarService carService;
+//    @Autowired
+//    OrganizationService organizationService;
+//    @Autowired
+//    AreaService areaService;
+//    @Autowired
+//    CarGongCheShouFeiDao carGongCheShouFeiDao;
+//
+//    /**
+//     * 执行任务
+//     */
+//    @Test
+//    void runJob() {
+//        // 数据目录
+//        Path dir = Paths.get("test/data/che-liang-diao-du");
+//        try (Stream<Path> stream = Files.list(dir)) {
+//            // 获取数据目录下的文件列表
+//            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+//            log.info("数据文件列表: {}", pathList);
+//            if (CollectionUtils.isEmpty(pathList)) {
+//                throw new MyRuntimeException("没有文件");
+//            }
+//            for (Path path : pathList) {
+//                singleJob(path);
+//            }
+//        } catch (Exception e) {
+//            log.error(e.getMessage(), e);
+//        }
+//    }
+//
+//    /**
+//     * 处理单个文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public void singleJob(Path path) throws Exception {
+//        List<Map<String, String>> list = readFile(path);
+//        List<Map<String, String>> distinctList = dataProcessing(path, list);
+//        Path csvPath = toCsv(path, distinctList);
+//    }
+//
+//    /**
+//     * 读取文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public List<Map<String, String>> readFile(Path path) throws Exception {
+//        Integer yearMonth = 202401;
+//        List<Map<String, String>> staffs = carGongCheShouFeiDao.getStaffs(yearMonth);
+//        log.info("读取: {}", path);
+//        List<String> headers = Stream.of("pai_qian_dan_bian_hao", "shen_qing_dan_bian_hao", "che_pai_hao",
+//                "shen_qing_ren", "shen_qing_dan_wei", "yong_che_ren", "yong_che_dan_wei", "mu_di_di",
+//                "yong_che_ren_shu", "chu_che_shi_you", "yong_che_ren_dian_hua", "shen_qing_yong_che_shi_jian",
+//                "shen_qing_fan_hui_shi_jian", "shi_ji_fan_hui_shi_jian", "diao_du_zhuang_tai", "diao_du_yuan",
+//                "diao_du_shi_jian").toList();
+//        try (InputStream inputStream = Files.newInputStream(path);
+//             Workbook workbook = new XSSFWorkbook(inputStream)
+//        ) {
+//            List<Map<String, String>> resultList = new ArrayList<>();
+//            // 读取第一个工作表
+//            Sheet sheet = workbook.getSheetAt(0);
+//            // 表头行
+//            Row headerRow = sheet.getRow(0);
+//            // 列数
+//            int columnCount = headerRow.getPhysicalNumberOfCells();
+//            log.info("columnCount: {}", columnCount);
+//            // 最后行数
+//            int lastRowNum = sheet.getLastRowNum();
+//            log.info("lastRowNum: {}", lastRowNum);
+//            if (lastRowNum == 0) {
+//                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+//            }
+//            // 遍历行
+//            for (int i = 1; i <= lastRowNum; i++) {
+//                Row row = sheet.getRow(i);
+//                if (row == null) {
+//                    continue;
+//                }
+//                Map<String, String> rowMap = new LinkedHashMap<>();
+//                // 遍历列
+//                for (int j = 0; j < columnCount; j++) {
+//                    String header = headers.get(j);
+//                    String cellValue = "";
+//                    rowMap.put(header, cellValue);
+//                    Cell cell = row.getCell(j);
+//                    if (cell == null) {
+//                        continue;
+//                    }
+//                    switch (cell.getCellType()) {
+//                        case STRING:
+//                            boolean skipTrim = "shen_qing_yong_che_shi_jian".equals(header)
+//                                    || "shen_qing_fan_hui_shi_jian".equals(header)
+//                                    || "shi_ji_fan_hui_shi_jian".equals(header)
+//                                    || "diao_du_shi_jian".equals(header);
+//                            // 删除字符串空白字符
+//                            cellValue = skipTrim ? cell.getStringCellValue()
+//                                    : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+//                            break;
+//                        case NUMERIC:
+//                            if (DateUtil.isCellDateFormatted(cell)) {
+//                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+//                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+//                                break;
+//                            }
+//                            cellValue = String.valueOf(cell.getNumericCellValue());
+//                            break;
+//                        case BOOLEAN:
+//                            cellValue = String.valueOf(cell.getBooleanCellValue());
+//                            break;
+//                        default:
+//                            break;
+//                    }
+//                    rowMap.put(headers.get(j), cellValue);
+//                }
+//                filter1(resultList, rowMap, staffs);
+//            }
+//            return resultList;
+//        }
+//    }
+//
+//    public void filter1(List<Map<String, String>> list, Map<String, String> map, List<Map<String, String>> staffs) {
+//        String chuCheShiYou = Objects.requireNonNullElse(map.get("chu_che_shi_you"), "");
+//        String muDiDi = Objects.requireNonNullElse(map.get("mu_di_di"), "");
+//        String yongCheRen = Objects.requireNonNullElse(map.get("yong_che_ren"), "");
+//        boolean flag = (StringUtils.containsAny(chuCheShiYou, "出差", "开会", "会议", "接站",
+//                "培训", "送站", "送机", "接站", "接人")
+//                && !StringUtils.containsAny(muDiDi, "政府", "市委", "委员会")
+//                && !StringUtils.containsAny(chuCheShiYou, "保障"))
+//                || (StringUtils.containsAny(muDiDi, "机场", "站")
+//                && !StringUtils.containsAny(muDiDi, "基站", "收费站", "公交站", "加油站", "服务站",
+//                "检查站", "街", "路", "检测站", "液化气站")
+//                && !StringUtils.containsAny(chuCheShiYou, "政府会议", "障", "省公司", "省分", "集团",
+//                "勘察", "调研", "审计", "巡视", "调测", "维护", "修", "处理", "设备", "查", "客户", "交流", "办事", "访"));
+//        if (flag) {
+//            for (Map<String, String> staff : staffs) {
+//                // 用车人和用车事由包含交通补贴人员
+//                if (yongCheRen.replaceAll("[^一-龥]", "").equals(staff)
+//                        || chuCheShiYou.contains(staff)) {
+//                    list.add(map);
+//                    break;
+//                }
+//            }
+//        }
+//    }
+//
+//    /**
+//     * 数据加工
+//     *
+//     * @param path 文件路径
+//     * @param list 数据
+//     */
+//    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+//        Set<String> specialCar = carGongCheShouFeiDao.getSpecialCar();
+//        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+//        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+//        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+//        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+//                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+//        List<AreaPo> cities = areaService.getCities();
+//        List<AreaPo> districts = areaService.getDistricts();
+//        Map<String, AreaPo> areaMap = areaService.getAreaMap(cities, districts);
+//        Map<String, List<AreaPo>> districtListMap = areaService.getDistrictListMap(cities, districts);
+//        List<Map<String, String>> resultList = new ArrayList<>();
+//        for (Map<String, String> map : list) {
+////            String shenQingYongCheShiJian = map.get("shen_qing_yong_che_shi_jian");
+////            LocalDateTime localDateTime = LocalDateTime.parse(shenQingYongCheShiJian, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+////            String yearMonth = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
+////            String year = String.valueOf(localDateTime.getYear());
+////            String month = String.valueOf(localDateTime.getMonthValue());
+////            map.put("year_month", yearMonth);
+////            map.put("year_no", year);
+////            map.put("month_no", month);
+//            String rawChePaiHao = map.get("che_pai_hao");
+////            map.put("raw_che_pai_hao", rawChePaiHao);
+//            String chePaiHao = carService.getChePai(rawChePaiHao);
+//            map.put("che_pai_hao", chePaiHao);
+////            String chePaiFail = carService.chePaiFail(rawChePaiHao);
+////            map.put("che_pai_fail", chePaiFail);
+//            String yongCheDanWei = map.get("yong_che_dan_wei");
+//            String firstUnit = carService.getFirstUnit(yongCheDanWei);
+//            map.put("first_unit", firstUnit);
+//            String secondUnit = carService.getSecondUnit(yongCheDanWei, firstUnit);
+//            map.put("second_unit", secondUnit);
+//            String thirdUnit = carService.getThirdUnit(yongCheDanWei, secondUnit);
+//            map.put("third_unit", thirdUnit);
+////            String areaNo = carService.getAreaNo(secondOrgs, yongCheDanWei);
+////            map.put("area_no", areaNo);
+////            String areaName = carService.getOrgName(orgMap, areaNo);
+////            map.put("area_name", areaName);
+////            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, yongCheDanWei);
+////            map.put("city_no", cityNo);
+////            String cityName = carService.getOrgName(orgMap, cityNo);
+////            map.put("city_name", cityName);
+////            String areaNo2 = carService.getAreaNo2(areaName, cityName);
+////            map.put("area_no2", areaNo2);
+////            String areaName2 = carService.getOrgName(orgMap, areaNo2);
+////            map.put("area_name2", areaName2);
+////            String cityId = carService.getCityId(cities, yongCheDanWei);
+////            map.put("city_id", cityId);
+////            String city = carService.getAreaName(areaMap, cityId);
+////            map.put("city", city);
+////            String districtId = carService.getDistrictId(districtListMap, cityId, cityName, yongCheDanWei);
+////            map.put("district_id", districtId);
+////            String district = carService.getAreaName(areaMap, districtId);
+////            map.put("district", district);
+////            map.put("source", path.getFileName().toString());
+//            filter2(resultList, map, specialCar);
+//        }
+//        return resultList;
+//    }
+//
+//    public void filter2(List<Map<String, String>> list, Map<String, String> map, Set<String> specialCar) {
+//        String chePaiHao = map.get("che_pai_hao");
+//        if (specialCar.contains(chePaiHao)) {
+//            log.info("特殊车辆: {}", chePaiHao);
+//            return;
+//        }
+//        String shenQingYongCheShiJian = map.get("shen_qing_yong_che_shi_jian");
+//        String shiJiFanHuiShiJian = map.get("shi_ji_fan_hui_shi_jian");
+//        LocalDateTime startLocalDateTime = null;
+//        LocalDateTime endLocalDateTime = null;
+//        try {
+//            startLocalDateTime = LocalDateTime.parse(shenQingYongCheShiJian,
+//                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//            endLocalDateTime = LocalDateTime.parse(shiJiFanHuiShiJian,
+//                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//        } catch (Exception e1) {
+//            try {
+//                startLocalDateTime = LocalDate.parse(shenQingYongCheShiJian,
+//                        DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+//                endLocalDateTime = LocalDate.parse(shiJiFanHuiShiJian,
+//                        DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+//            } catch (Exception e2) {
+//                log.error("时间格式化失败: {} -> {}", shenQingYongCheShiJian, shiJiFanHuiShiJian);
+//            }
+//        }
+//        if (endLocalDateTime == null) {
+//            endLocalDateTime = startLocalDateTime;
+//        }
+//        // 查询行驶里程
+//        BigDecimal liCheng = carGongCheShouFeiDao.getCarLiChengDayByChePaiAndDate(chePaiHao,
+//                startLocalDateTime.toLocalDate(), endLocalDateTime.toLocalDate());
+////        if (liCheng == null) {
+////            return;
+////        }
+////        if (liCheng.compareTo(BigDecimal.ZERO) == 0 || liCheng.compareTo(new BigDecimal("20")) > 0) {
+////            return;
+////        }
+////        if (liCheng != null && liCheng.compareTo(new BigDecimal("20")) > 0) {
+////            return;
+////        }
+//        map.put("li_cheng", liCheng == null ? null : liCheng.toString());
+//        list.add(map);
+//    }
+//
+//    /**
+//     * 生成csv
+//     *
+//     * @param path 源文件路径
+//     * @param list 数据
+//     */
+//    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+//        log.info("条数:{}", list.size());
+//        Files.createDirectories(Paths.get("test/history/"));
+//        Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv");
+//        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+//                StandardCharsets.UTF_8);
+//             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+//            // 添加bom头避免excel乱码
+//            osw.write('\ufeff');
+////            Map<String, String> header = list.get(0);
+////            // 表头
+////            printer.printRecord(header.keySet());
+//            printer.printRecord("派遣单编号","申请单编号","车牌号","申请人","申请单位","用车人","用车单位","目的地","用车人数","出车事由","用车人电话","申请用车时间","申请返回时间","实际返回时间","调度状态","调度员","调度时间", "用车单位一级", "用车单位二级", "用车单位三级", "日里程");
+//            for (Map<String, String> map : list) {
+//                printer.printRecord(map.values());
+//            }
+//        }
+//        return csvPath;
+//    }
+//}

+ 329 - 0
src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests1.java

@@ -0,0 +1,329 @@
+//package com.nokia.finance.tasks.car;
+//
+//import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+//import com.nokia.finance.tasks.dao.car.CarGongCheShouFeiDao;
+//import com.nokia.finance.tasks.pojo.po.common.AreaPo;
+//import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+//import com.nokia.finance.tasks.service.car.CarService;
+//import com.nokia.finance.tasks.service.common.AreaService;
+//import com.nokia.finance.tasks.service.common.OrganizationService;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.csv.CSVFormat;
+//import org.apache.commons.csv.CSVPrinter;
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.poi.ss.usermodel.Cell;
+//import org.apache.poi.ss.usermodel.DateUtil;
+//import org.apache.poi.ss.usermodel.Row;
+//import org.apache.poi.ss.usermodel.Sheet;
+//import org.apache.poi.ss.usermodel.Workbook;
+//import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+//import org.junit.jupiter.api.Test;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//import org.springframework.test.context.ActiveProfiles;
+//import org.springframework.util.CollectionUtils;
+//
+//import java.io.InputStream;
+//import java.io.OutputStreamWriter;
+//import java.math.BigDecimal;
+//import java.nio.charset.StandardCharsets;
+//import java.nio.file.Files;
+//import java.nio.file.Path;
+//import java.nio.file.Paths;
+//import java.time.LocalDate;
+//import java.time.LocalDateTime;
+//import java.time.format.DateTimeFormatter;
+//import java.util.ArrayList;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Objects;
+//import java.util.Set;
+//import java.util.stream.Stream;
+//
+//@Slf4j
+//@SpringBootTest
+//@ActiveProfiles("dev")
+//class CarGongCheShiYongTests1 {
+//    @Autowired
+//    CarService carService;
+//    @Autowired
+//    OrganizationService organizationService;
+//    @Autowired
+//    AreaService areaService;
+//    @Autowired
+//    CarGongCheShouFeiDao carGongCheShouFeiDao;
+//
+//    /**
+//     * 执行任务
+//     */
+//    @Test
+//    void runJob() {
+//        // 数据目录
+//        Path dir = Paths.get("test/data/che-liang-diao-du");
+//        try (Stream<Path> stream = Files.list(dir)) {
+//            // 获取数据目录下的文件列表
+//            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+//            log.info("数据文件列表: {}", pathList);
+//            if (CollectionUtils.isEmpty(pathList)) {
+//                throw new MyRuntimeException("没有文件");
+//            }
+//            for (Path path : pathList) {
+//                singleJob(path);
+//            }
+//        } catch (Exception e) {
+//            log.error(e.getMessage(), e);
+//        }
+//    }
+//
+//    /**
+//     * 处理单个文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public void singleJob(Path path) throws Exception {
+//        List<Map<String, String>> list = readFile(path);
+//        List<Map<String, String>> distinctList = dataProcessing(path, list);
+//        Path csvPath = toCsv(path, distinctList);
+//    }
+//
+//    /**
+//     * 读取文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public List<Map<String, String>> readFile(Path path) throws Exception {
+//        Integer yearMonth = 202401;
+//        List<String> staffs = carGongCheShouFeiDao.getStaffs(yearMonth);
+//        log.info("读取: {}", path);
+//        List<String> headers = Stream.of("pai_qian_dan_bian_hao", "shen_qing_dan_bian_hao", "che_pai_hao",
+//                "shen_qing_ren", "shen_qing_dan_wei", "yong_che_ren", "yong_che_dan_wei", "mu_di_di",
+//                "yong_che_ren_shu", "chu_che_shi_you", "yong_che_ren_dian_hua", "shen_qing_yong_che_shi_jian",
+//                "shen_qing_fan_hui_shi_jian", "shi_ji_fan_hui_shi_jian", "diao_du_zhuang_tai", "diao_du_yuan",
+//                "diao_du_shi_jian").toList();
+//        try (InputStream inputStream = Files.newInputStream(path);
+//             Workbook workbook = new XSSFWorkbook(inputStream)
+//        ) {
+//            List<Map<String, String>> resultList = new ArrayList<>();
+//            // 读取第一个工作表
+//            Sheet sheet = workbook.getSheetAt(0);
+//            // 表头行
+//            Row headerRow = sheet.getRow(0);
+//            // 列数
+//            int columnCount = headerRow.getPhysicalNumberOfCells();
+//            log.info("columnCount: {}", columnCount);
+//            // 最后行数
+//            int lastRowNum = sheet.getLastRowNum();
+//            log.info("lastRowNum: {}", lastRowNum);
+//            if (lastRowNum == 0) {
+//                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+//            }
+//            // 遍历行
+//            for (int i = 1; i <= lastRowNum; i++) {
+//                Row row = sheet.getRow(i);
+//                if (row == null) {
+//                    continue;
+//                }
+//                Map<String, String> rowMap = new LinkedHashMap<>();
+//                // 遍历列
+//                for (int j = 0; j < columnCount; j++) {
+//                    String header = headers.get(j);
+//                    String cellValue = "";
+//                    rowMap.put(header, cellValue);
+//                    Cell cell = row.getCell(j);
+//                    if (cell == null) {
+//                        continue;
+//                    }
+//                    switch (cell.getCellType()) {
+//                        case STRING:
+//                            boolean skipTrim = "shen_qing_yong_che_shi_jian".equals(header)
+//                                    || "shen_qing_fan_hui_shi_jian".equals(header)
+//                                    || "shi_ji_fan_hui_shi_jian".equals(header)
+//                                    || "diao_du_shi_jian".equals(header);
+//                            // 删除字符串空白字符
+//                            cellValue = skipTrim ? cell.getStringCellValue()
+//                                    : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+//                            break;
+//                        case NUMERIC:
+//                            if (DateUtil.isCellDateFormatted(cell)) {
+//                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+//                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+//                                break;
+//                            }
+//                            cellValue = String.valueOf(cell.getNumericCellValue());
+//                            break;
+//                        case BOOLEAN:
+//                            cellValue = String.valueOf(cell.getBooleanCellValue());
+//                            break;
+//                        default:
+//                            break;
+//                    }
+//                    rowMap.put(headers.get(j), cellValue);
+//                }
+//                filter1(resultList, rowMap, staffs);
+//            }
+//            return resultList;
+//        }
+//    }
+//
+//    public void filter1(List<Map<String, String>> list, Map<String, String> map, List<String> staffs) {
+//        String chuCheShiYou = Objects.requireNonNullElse(map.get("chu_che_shi_you"), "");
+//        String muDiDi = Objects.requireNonNullElse(map.get("mu_di_di"), "");
+//        String yongCheRen = Objects.requireNonNullElse(map.get("yong_che_ren"), "");
+//        boolean flag = (StringUtils.containsAny(chuCheShiYou, "出差", "开会", "会议", "接站",
+//                "培训", "送站", "送机", "接站", "接人")
+//                && !StringUtils.containsAny(muDiDi, "政府", "市委", "委员会")
+//                && !StringUtils.containsAny(chuCheShiYou, "保障"))
+//                || (StringUtils.containsAny(muDiDi, "机场", "站")
+//                && !StringUtils.containsAny(muDiDi, "基站", "收费站", "公交站", "加油站", "服务站",
+//                "检查站", "街", "路", "检测站", "液化气站")
+//                && !StringUtils.containsAny(chuCheShiYou, "政府会议", "障", "省公司", "省分", "集团",
+//                "勘察", "调研", "审计", "巡视", "调测", "维护", "修", "处理", "设备", "查", "客户", "交流", "办事", "访"));
+//        if (flag) {
+//            for (String staff : staffs) {
+//                // 用车人和用车事由包含交通补贴人员
+//                if (yongCheRen.replaceAll("[^一-龥]", "").equals(staff)
+//                        || chuCheShiYou.contains(staff)) {
+//                    list.add(map);
+//                    break;
+//                }
+//            }
+//        }
+//    }
+//
+//    /**
+//     * 数据加工
+//     *
+//     * @param path 文件路径
+//     * @param list 数据
+//     */
+//    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+//        Set<String> specialCar = carGongCheShouFeiDao.getSpecialCar();
+//        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+//        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+//        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+//        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+//                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+//        List<AreaPo> cities = areaService.getCities();
+//        List<AreaPo> districts = areaService.getDistricts();
+//        Map<String, AreaPo> areaMap = areaService.getAreaMap(cities, districts);
+//        Map<String, List<AreaPo>> districtListMap = areaService.getDistrictListMap(cities, districts);
+//        List<Map<String, String>> resultList = new ArrayList<>();
+//        for (Map<String, String> map : list) {
+////            String shenQingYongCheShiJian = map.get("shen_qing_yong_che_shi_jian");
+////            LocalDateTime localDateTime = LocalDateTime.parse(shenQingYongCheShiJian, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+////            String yearMonth = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
+////            String year = String.valueOf(localDateTime.getYear());
+////            String month = String.valueOf(localDateTime.getMonthValue());
+////            map.put("year_month", yearMonth);
+////            map.put("year_no", year);
+////            map.put("month_no", month);
+//            String rawChePaiHao = map.get("che_pai_hao");
+////            map.put("raw_che_pai_hao", rawChePaiHao);
+//            String chePaiHao = carService.getChePai(rawChePaiHao);
+//            map.put("che_pai_hao", chePaiHao);
+////            String chePaiFail = carService.chePaiFail(rawChePaiHao);
+////            map.put("che_pai_fail", chePaiFail);
+//            String yongCheDanWei = map.get("yong_che_dan_wei");
+//            String firstUnit = carService.getFirstUnit(yongCheDanWei);
+//            map.put("first_unit", firstUnit);
+//            String secondUnit = carService.getSecondUnit(yongCheDanWei, firstUnit);
+//            map.put("second_unit", secondUnit);
+//            String thirdUnit = carService.getThirdUnit(yongCheDanWei, secondUnit);
+//            map.put("third_unit", thirdUnit);
+////            String areaNo = carService.getAreaNo(secondOrgs, yongCheDanWei);
+////            map.put("area_no", areaNo);
+////            String areaName = carService.getOrgName(orgMap, areaNo);
+////            map.put("area_name", areaName);
+////            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, yongCheDanWei);
+////            map.put("city_no", cityNo);
+////            String cityName = carService.getOrgName(orgMap, cityNo);
+////            map.put("city_name", cityName);
+////            String areaNo2 = carService.getAreaNo2(areaName, cityName);
+////            map.put("area_no2", areaNo2);
+////            String areaName2 = carService.getOrgName(orgMap, areaNo2);
+////            map.put("area_name2", areaName2);
+////            String cityId = carService.getCityId(cities, yongCheDanWei);
+////            map.put("city_id", cityId);
+////            String city = carService.getAreaName(areaMap, cityId);
+////            map.put("city", city);
+////            String districtId = carService.getDistrictId(districtListMap, cityId, cityName, yongCheDanWei);
+////            map.put("district_id", districtId);
+////            String district = carService.getAreaName(areaMap, districtId);
+////            map.put("district", district);
+////            map.put("source", path.getFileName().toString());
+//            filter2(resultList, map, specialCar);
+//        }
+//        return resultList;
+//    }
+//
+//    public void filter2(List<Map<String, String>> list, Map<String, String> map, Set<String> specialCar) {
+//        String chePaiHao = map.get("che_pai_hao");
+//        if (specialCar.contains(chePaiHao)) {
+//            log.info("特殊车辆: {}", chePaiHao);
+//            return;
+//        }
+//        String shenQingYongCheShiJian = map.get("shen_qing_yong_che_shi_jian");
+//        String shiJiFanHuiShiJian = map.get("shi_ji_fan_hui_shi_jian");
+//        LocalDateTime startLocalDateTime = null;
+//        LocalDateTime endLocalDateTime = null;
+//        try {
+//            startLocalDateTime = LocalDateTime.parse(shenQingYongCheShiJian,
+//                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//            endLocalDateTime = LocalDateTime.parse(shiJiFanHuiShiJian,
+//                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//        } catch (Exception e1) {
+//            try {
+//                startLocalDateTime = LocalDate.parse(shenQingYongCheShiJian,
+//                        DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+//                endLocalDateTime = LocalDate.parse(shiJiFanHuiShiJian,
+//                        DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+//            } catch (Exception e2) {
+//                log.error("时间格式化失败: {} -> {}", shenQingYongCheShiJian, shiJiFanHuiShiJian);
+//            }
+//        }
+//        if (endLocalDateTime == null) {
+//            endLocalDateTime = startLocalDateTime;
+//        }
+//        // 查询行驶里程
+//        BigDecimal liCheng = carGongCheShouFeiDao.getCarLiChengDayByChePaiAndDate(chePaiHao,
+//                startLocalDateTime.toLocalDate(), endLocalDateTime.toLocalDate());
+////        if (liCheng == null) {
+////            return;
+////        }
+////        if (liCheng.compareTo(BigDecimal.ZERO) == 0 || liCheng.compareTo(new BigDecimal("20")) > 0) {
+////            return;
+////        }
+////        if (liCheng != null && liCheng.compareTo(new BigDecimal("20")) > 0) {
+////            return;
+////        }
+//        map.put("li_cheng", liCheng == null ? null : liCheng.toString());
+//        list.add(map);
+//    }
+//
+//    /**
+//     * 生成csv
+//     *
+//     * @param path 源文件路径
+//     * @param list 数据
+//     */
+//    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+//        log.info("条数:{}", list.size());
+//        Files.createDirectories(Paths.get("test/history/"));
+//        Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv");
+//        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+//                StandardCharsets.UTF_8);
+//             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+//            // 添加bom头避免excel乱码
+//            osw.write('\ufeff');
+////            Map<String, String> header = list.get(0);
+////            // 表头
+////            printer.printRecord(header.keySet());
+//            printer.printRecord("派遣单编号","申请单编号","车牌号","申请人","申请单位","用车人","用车单位","目的地","用车人数","出车事由","用车人电话","申请用车时间","申请返回时间","实际返回时间","调度状态","调度员","调度时间", "用车单位一级", "用车单位二级", "用车单位三级", "日里程");
+//            for (Map<String, String> map : list) {
+//                printer.printRecord(map.values());
+//            }
+//        }
+//        return csvPath;
+//    }
+//}

+ 438 - 0
src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests2.java

@@ -0,0 +1,438 @@
+//package com.nokia.finance.tasks.car;
+//
+//import com.google.gson.Gson;
+//import com.google.gson.reflect.TypeToken;
+//import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+//import com.nokia.finance.tasks.dao.car.CarGongCheShouFeiDao;
+//import com.nokia.finance.tasks.pojo.po.common.AreaPo;
+//import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+//import com.nokia.finance.tasks.service.car.CarService;
+//import com.nokia.finance.tasks.service.common.AreaService;
+//import com.nokia.finance.tasks.service.common.OrganizationService;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.csv.CSVFormat;
+//import org.apache.commons.csv.CSVPrinter;
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.poi.ss.usermodel.Cell;
+//import org.apache.poi.ss.usermodel.DateUtil;
+//import org.apache.poi.ss.usermodel.Row;
+//import org.apache.poi.ss.usermodel.Sheet;
+//import org.apache.poi.ss.usermodel.Workbook;
+//import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+//import org.junit.jupiter.api.Test;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//import org.springframework.test.context.ActiveProfiles;
+//import org.springframework.util.CollectionUtils;
+//
+//import java.io.InputStream;
+//import java.io.OutputStreamWriter;
+//import java.math.BigDecimal;
+//import java.nio.charset.StandardCharsets;
+//import java.nio.file.Files;
+//import java.nio.file.Path;
+//import java.nio.file.Paths;
+//import java.time.LocalDate;
+//import java.time.LocalDateTime;
+//import java.time.format.DateTimeFormatter;
+//import java.util.ArrayList;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Objects;
+//import java.util.Set;
+//import java.util.stream.Stream;
+//
+//@Slf4j
+//@SpringBootTest
+//@ActiveProfiles("dev")
+//class CarGongCheShiYongTests2 {
+//    @Autowired
+//    CarService carService;
+//    @Autowired
+//    OrganizationService organizationService;
+//    @Autowired
+//    AreaService areaService;
+//    @Autowired
+//    CarGongCheShouFeiDao carGongCheShouFeiDao;
+//
+//    /**
+//     * 执行任务
+//     */
+//    @Test
+//    void runJob() {
+//        // 数据目录
+//        Path dir = Paths.get("test/data/ycxxzl");
+//        try (Stream<Path> stream = Files.list(dir)) {
+//            // 获取数据目录下的文件列表
+//            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+//            log.info("数据文件列表: {}", pathList);
+//            if (CollectionUtils.isEmpty(pathList)) {
+//                throw new MyRuntimeException("没有文件");
+//            }
+//            for (Path path : pathList) {
+//                singleJob(path);
+//            }
+//        } catch (Exception e) {
+//            log.error(e.getMessage(), e);
+//        }
+//    }
+//
+//    /**
+//     * 处理单个文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public void singleJob(Path path) throws Exception {
+//        List<Map<String, String>> list = readFile(path);
+//        List<Map<String, String>> distinctList = dataProcessing(path, list);
+//        Path csvPath = toCsv(path, distinctList);
+//    }
+//
+//    /**
+//     * 读取文件
+//     *
+//     * @param path 文件路径
+//     */
+//    public List<Map<String, String>> readFile(Path path) throws Exception {
+//        log.info("读取: {}", path);
+//        try (InputStream inputStream = Files.newInputStream(path);
+//             Workbook workbook = new XSSFWorkbook(inputStream)
+//        ) {
+//            List<Map<String, String>> resultList = new ArrayList<>();
+//            // 读取第一个工作表
+//            Sheet sheet = workbook.getSheetAt(0);
+//            // 最后行数
+//            int lastRowNum = sheet.getLastRowNum();
+//            log.info("lastRowNum: {}", lastRowNum);
+//            if (lastRowNum == 0) {
+//                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+//            }
+//            Gson gson = new Gson();
+//            int currentRowNum = 0;
+//            while (currentRowNum <= lastRowNum) {
+//                log.info(">>>>>>>>>>currentRowNum: {}", currentRowNum);
+//                Map<String, String> rowMap = new LinkedHashMap<>();
+//                // 申请单表头行
+//                Row row1 = sheet.getRow(currentRowNum);
+//                // 申请单数据行
+//                Row row2 = sheet.getRow(++currentRowNum);
+//                if (currentRowNum > lastRowNum) {
+//                    break;
+//                }
+//                List<String> headers1;
+//                int lastCellNum1 = row1.getLastCellNum();
+//                headers1 = switch (lastCellNum1) {
+//                    case 9 ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_qing_shi_jian").toList();
+//                    case 13 ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_qing_shi_jian").toList();
+//                    case 17 ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_pi_ren2", "shen_pi_jie_guo2", "shen_pi_shi_jian2", "shen_pi_yi_jian2", "shen_qing_shi_jian").toList();
+//                    default ->
+//                            Stream.of("shen_qing_dan_hao", "shen_qing_ren", "shen_qing_ren_dan_wei", "shen_qing_lei_xing", "yong_che_ren", "yong_che_ren_dan_wei", "yong_che_shi_you", "shen_qing_dan_zhuang_tai", "shen_pi_ren1", "shen_pi_jie_guo1", "shen_pi_shi_jian1", "shen_pi_yi_jian1", "shen_pi_ren2", "shen_pi_jie_guo2", "shen_pi_shi_jian2", "shen_pi_yi_jian2", "shen_pi_ren3", "shen_pi_jie_guo3", "shen_pi_shi_jian3", "shen_pi_yi_jian3", "shen_qing_shi_jian").toList();
+//                };
+//
+//                int headerSize1 = headers1.size();
+//                for (int i = 0; i < headerSize1; i++) {
+//                    String header = headers1.get(i);
+//                    Cell cell = row2.getCell(i);
+//                    String cellValue = "";
+//                    switch (cell.getCellType()) {
+//                        case STRING:
+//                            boolean skipTrim = "shen_qing_shi_jian".equals(header)
+//                                    || "shen_pi_shi_jian1".equals(header)
+//                                    || "shen_pi_shi_jian2".equals(header)
+//                                    || "shen_pi_shi_jian3".equals(header);
+//                            // 删除字符串空白字符
+//                            cellValue = skipTrim ? cell.getStringCellValue()
+//                                    : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+//                            break;
+//                        case NUMERIC:
+//                            if (DateUtil.isCellDateFormatted(cell)) {
+//                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+//                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+//                                break;
+//                            }
+//                            cellValue = String.valueOf(cell.getNumericCellValue());
+//                            break;
+//                        case BOOLEAN:
+//                            cellValue = String.valueOf(cell.getBooleanCellValue());
+//                            break;
+//                        default:
+//                            break;
+//                    }
+//                    rowMap.put(header, cellValue);
+//                }
+//                ++currentRowNum;
+//                if (currentRowNum > lastRowNum) {
+//                    filter1(resultList, rowMap);
+//                    break;
+//                }
+//                if (!"派遣单编号".equals(sheet.getRow(currentRowNum).getCell(0).getStringCellValue())) {
+//                    filter1(resultList, rowMap);
+//                    continue;
+//                }
+//
+//                while (currentRowNum <= lastRowNum) {
+//                    Map<String, String> rowMapCopy = gson.fromJson(gson.toJson(rowMap), new TypeToken<>() {});
+//                    // 派遣单表头行
+//                    Row row3 = sheet.getRow(currentRowNum);
+//                    if (!"派遣单编号".equals(row3.getCell(0).getStringCellValue())) {
+//                        break;
+//                    }
+//                    Row row4 = sheet.getRow(++currentRowNum);
+//                    if (currentRowNum > lastRowNum) {
+//                        break;
+//                    }
+//                    List<String> headers2 = Stream.of("pai_qian_dan_bian_hao", "che_pai_hao", "jia_shi_yuan", "chu_che_shi_jian", "gui_dui_shi_jian", "pai_qian_che_liang_zhuang_tai", "ren_wu_zhi_xing_zhuang_tai").toList();
+//                    int headersSize2 = headers2.size();
+//                    for (int i = 0; i < headersSize2; i++) {
+//                        String header = headers2.get(i);
+//                        Cell cell = row4.getCell(i);
+//                        String cellValue = "";
+//                        switch (cell.getCellType()) {
+//                            case STRING:
+//                                boolean skipTrim = "chu_che_shi_jian".equals(header)
+//                                        || "gui_dui_shi_jian".equals(header);
+//                                // 删除字符串空白字符
+//                                cellValue = skipTrim ? cell.getStringCellValue()
+//                                        : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+//                                break;
+//                            case NUMERIC:
+//                                if (DateUtil.isCellDateFormatted(cell)) {
+//                                    cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+//                                            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+//                                    break;
+//                                }
+//                                cellValue = String.valueOf(cell.getNumericCellValue());
+//                                break;
+//                            case BOOLEAN:
+//                                cellValue = String.valueOf(cell.getBooleanCellValue());
+//                                break;
+//                            default:
+//                                break;
+//                        }
+//                        rowMapCopy.put(header, cellValue);
+//                    }
+//                    filter1(resultList, rowMapCopy);
+//                    currentRowNum++;
+//                }
+//            }
+//            return resultList;
+//        }
+//    }
+//
+//    public void filter1(List<Map<String, String>> list, Map<String, String> map) {
+//        String shenQingDanZhuangTai = map.get("shen_qing_dan_zhuang_tai");
+//        if (!"已完成".equals(shenQingDanZhuangTai)) {
+//            return;
+//        }
+//        String yongCheShiYou = Objects.requireNonNullElse(map.get("yong_che_shi_you"), "");
+//        boolean flag = StringUtils.containsAny(yongCheShiYou, "出差", "开会", "会议", "接站",
+//                "培训", "送站", "送机", "接站", "接人", "机场", "站")
+//                && !StringUtils.containsAny(yongCheShiYou, "障", "营销", "查", "物料", "省公司",
+//                "省分", "集团", "勘察", "调研", "审计", "巡视", "调测", "维护", "修", "处理", "设备", "客户", "交流", "办事",
+//                "访", "政府", "市委", "委员会", "县委", "基站", "收费站", "公交站", "加油站", "服务站", "检查站", "街", "路",
+//                "检测站", "液化气站", "总部");
+//        if (flag) {
+//            list.add(map);
+//        }
+//    }
+//
+//    /**
+//     * 数据加工
+//     *
+//     * @param path 文件路径
+//     * @param list 数据
+//     */
+//    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+//        Integer yearMonth = 202402;
+//        List<Map<String, String>> staffs = carGongCheShouFeiDao.getStaffs(yearMonth);
+//        Set<String> specialCar = carGongCheShouFeiDao.getSpecialCar();
+//        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+//        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+//        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+//        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+//                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+//        List<AreaPo> cities = areaService.getCities();
+//        List<AreaPo> districts = areaService.getDistricts();
+//        Map<String, AreaPo> areaMap = areaService.getAreaMap(cities, districts);
+//        Map<String, List<AreaPo>> districtListMap = areaService.getDistrictListMap(cities, districts);
+//        List<Map<String, String>> resultList = new ArrayList<>();
+//        for (Map<String, String> map : list) {
+////            String shenQingYongCheShiJian = map.get("shen_qing_yong_che_shi_jian");
+////            LocalDateTime localDateTime = LocalDateTime.parse(shenQingYongCheShiJian, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+////            String yearMonth = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
+////            String year = String.valueOf(localDateTime.getYear());
+////            String month = String.valueOf(localDateTime.getMonthValue());
+////            map.put("year_month", yearMonth);
+////            map.put("year_no", year);
+////            map.put("month_no", month);
+//            String rawChePaiHao = map.get("che_pai_hao");
+////            map.put("raw_che_pai_hao", rawChePaiHao);
+//            String chePaiHao = carService.getChePai(rawChePaiHao);
+//            map.put("che_pai_hao", chePaiHao);
+////            String chePaiFail = carService.chePaiFail(rawChePaiHao);
+////            map.put("che_pai_fail", chePaiFail);
+//            String yongCheRenDanWei = map.get("yong_che_ren_dan_wei");
+//            String firstUnit = carService.getFirstUnit(yongCheRenDanWei);
+//            map.put("first_unit", firstUnit);
+//            String secondUnit = carService.getSecondUnit(yongCheRenDanWei, firstUnit);
+//            map.put("second_unit", secondUnit);
+//            String thirdUnit = carService.getThirdUnit(yongCheRenDanWei, secondUnit);
+//            map.put("third_unit", thirdUnit);
+////            String areaNo = carService.getAreaNo(secondOrgs, yongCheDanWei);
+////            map.put("area_no", areaNo);
+////            String areaName = carService.getOrgName(orgMap, areaNo);
+////            map.put("area_name", areaName);
+////            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, yongCheDanWei);
+////            map.put("city_no", cityNo);
+////            String cityName = carService.getOrgName(orgMap, cityNo);
+////            map.put("city_name", cityName);
+////            String areaNo2 = carService.getAreaNo2(areaName, cityName);
+////            map.put("area_no2", areaNo2);
+////            String areaName2 = carService.getOrgName(orgMap, areaNo2);
+////            map.put("area_name2", areaName2);
+////            String cityId = carService.getCityId(cities, yongCheDanWei);
+////            map.put("city_id", cityId);
+////            String city = carService.getAreaName(areaMap, cityId);
+////            map.put("city", city);
+////            String districtId = carService.getDistrictId(districtListMap, cityId, cityName, yongCheDanWei);
+////            map.put("district_id", districtId);
+////            String district = carService.getAreaName(areaMap, districtId);
+////            map.put("district", district);
+////            map.put("source", path.getFileName().toString());
+//            filter2(resultList, map, specialCar, staffs);
+//        }
+//        return resultList;
+//    }
+//
+//    public void filter2(List<Map<String, String>> list, Map<String, String> map, Set<String> specialCar,
+//                        List<Map<String, String>> staffs) {
+//        String yongCheShiYou = Objects.requireNonNullElse(map.get("yong_che_shi_you"), "");
+//        String yongCheRen = Objects.requireNonNullElse(map.get("yong_che_ren"), "");
+//        String chePaiHao = map.get("che_pai_hao");
+//        String shenQingShiJian = map.get("shen_qing_shi_jian");
+//        String chuCheShiJian = map.get("chu_che_shi_jian");
+//        String guiDuiShiJian = map.get("gui_dui_shi_jian");
+//        String firstUnit1 = Objects.requireNonNullElse(map.get("first_unit"), "");
+//        boolean notInStaffs = true;
+//        for (Map<String, String> staff : staffs) {
+//            String firstUnit2 = staff.get("first_unit");
+//            String xingMing = staff.get("xing_ming");
+//            // 用车人或用车事由包含交通补贴人员且单位相同
+//            if (firstUnit1.equals(firstUnit2)
+//                    && (yongCheRen.replaceAll("[^一-龥]", "").equals(xingMing)
+//                    || yongCheShiYou.contains(xingMing))) {
+//                notInStaffs = false;
+//                break;
+//            }
+//        }
+//        if (notInStaffs) {
+//            return;
+//        }
+//        if (StringUtils.isBlank(chePaiHao)) {
+//            list.add(map);
+//            return;
+//        }
+//        if (specialCar.contains(chePaiHao)) {
+//            log.info("特殊车辆: {}", chePaiHao);
+//            return;
+//        }
+//        if (StringUtils.isBlank(chuCheShiJian)) {
+//            chuCheShiJian = shenQingShiJian;
+//        }
+//        if (StringUtils.isBlank(guiDuiShiJian)) {
+//            guiDuiShiJian = chuCheShiJian;
+//        }
+//        LocalDateTime startLocalDateTime = null;
+//        LocalDateTime endLocalDateTime = null;
+//        try {
+//            startLocalDateTime = LocalDateTime.parse(chuCheShiJian,
+//                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//        } catch (Exception e1) {
+//            try {
+//                startLocalDateTime = LocalDate.parse(chuCheShiJian,
+//                        DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+//            } catch (Exception e2) {
+//                log.error("时间格式化失败: {}", chuCheShiJian);
+//            }
+//        }
+//        try {
+//            endLocalDateTime = LocalDateTime.parse(guiDuiShiJian,
+//                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//        } catch (Exception e1) {
+//            try {
+//                endLocalDateTime = LocalDate.parse(guiDuiShiJian,
+//                        DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
+//            } catch (Exception e2) {
+//                log.error("时间格式化失败: {}", guiDuiShiJian);
+//            }
+//        }
+//        // 查询行驶里程
+//        BigDecimal liCheng = carGongCheShouFeiDao.getCarLiChengDayByChePaiAndDate(chePaiHao,
+//                startLocalDateTime.toLocalDate(), endLocalDateTime.toLocalDate());
+//        map.put("li_cheng", liCheng == null ? null : liCheng.toString());
+//        list.add(map);
+//    }
+//
+//    /**
+//     * 生成csv
+//     *
+//     * @param path 源文件路径
+//     * @param list 数据
+//     */
+//    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+//        log.info("条数:{}", list.size());
+//        Files.createDirectories(Paths.get("test/history/"));
+//        Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv");
+//        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+//                StandardCharsets.UTF_8);
+//             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+//            // 添加bom头避免excel乱码
+//            osw.write('\ufeff');
+////            Map<String, String> header = list.get(0);
+////            // 表头
+////            printer.printRecord(header.keySet());
+//            printer.printRecord("申请单号","申请人","申请人单位","申请类型","用车人","用车人单位","用车事由","申请单状态","申请时间","审批人1","审批结果1","审批时间1","审批意见1","审批人2","审批结果2","审批时间2","审批意见2","审批人3","审批结果3","审批时间3","审批意见3","派遣单编号","车牌号码","驾驶员","出车时间","归队时间","派遣车辆状态","任务执行状态", "用车单位一级", "用车单位二级", "用车单位三级", "里程");
+//            for (Map<String, String> map : list) {
+//                printer.printRecord(
+//                        map.get("shen_qing_dan_hao"),
+//                        map.get("shen_qing_ren"),
+//                        map.get("shen_qing_ren_dan_wei"),
+//                        map.get("shen_qing_lei_xing"),
+//                        map.get("yong_che_ren"),
+//                        map.get("yong_che_ren_dan_wei"),
+//                        map.get("yong_che_shi_you"),
+//                        map.get("shen_qing_dan_zhuang_tai"),
+//                        map.get("shen_qing_shi_jian"),
+//                        map.get("shen_pi_ren1"),
+//                        map.get("shen_pi_jie_guo1"),
+//                        map.get("shen_pi_shi_jian1"),
+//                        map.get("shen_pi_yi_jian1"),
+//                        map.get("shen_pi_ren2"),
+//                        map.get("shen_pi_jie_guo2"),
+//                        map.get("shen_pi_shi_jian2"),
+//                        map.get("shen_pi_yi_jian2"),
+//                        map.get("shen_pi_ren3"),
+//                        map.get("shen_pi_jie_guo3"),
+//                        map.get("shen_pi_shi_jian3"),
+//                        map.get("shen_pi_yi_jian3"),
+//                        map.get("pai_qian_dan_bian_hao"),
+//                        map.get("che_pai_hao"),
+//                        map.get("jia_shi_yuan"),
+//                        map.get("chu_che_shi_jian"),
+//                        map.get("gui_dui_shi_jian"),
+//                        map.get("pai_qian_che_liang_zhuang_tai"),
+//                        map.get("ren_wu_zhi_xing_zhuang_tai"),
+//                        map.get("first_unit"),
+//                        map.get("second_unit"),
+//                        map.get("third_unit"),
+//                        map.get("li_cheng")
+//                );
+//            }
+//        }
+//        return csvPath;
+//    }
+//}

+ 373 - 0
src/test/java/com/nokia/finance/tasks/car/CarGongCheShiYongTests3.java

@@ -0,0 +1,373 @@
+package com.nokia.finance.tasks.car;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.dao.car.CarGongCheShouFeiDao;
+import com.nokia.finance.tasks.pojo.po.common.AreaPo;
+import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+import com.nokia.finance.tasks.service.car.CarService;
+import com.nokia.finance.tasks.service.common.AreaService;
+import com.nokia.finance.tasks.service.common.OrganizationService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.util.CollectionUtils;
+
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class CarGongCheShiYongTests3 {
+    @Autowired
+    CarService carService;
+    @Autowired
+    OrganizationService organizationService;
+    @Autowired
+    AreaService areaService;
+    @Autowired
+    CarGongCheShouFeiDao carGongCheShouFeiDao;
+
+    /**
+     * 执行任务
+     */
+    @Test
+    void runJob() {
+        // 数据目录
+        Path dir = Paths.get("test/data/yctjfxmx");
+        try (Stream<Path> stream = Files.list(dir)) {
+            // 获取数据目录下的文件列表
+            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+            log.info("数据文件列表: {}", pathList);
+            if (CollectionUtils.isEmpty(pathList)) {
+                throw new MyRuntimeException("没有文件");
+            }
+            for (Path path : pathList) {
+                singleJob(path);
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 处理单个文件
+     *
+     * @param path 文件路径
+     */
+    public void singleJob(Path path) throws Exception {
+        List<Map<String, String>> list = readFile(path);
+        List<Map<String, String>> distinctList = dataProcessing(path, list);
+        Path csvPath = toCsv(path, distinctList);
+    }
+
+    /**
+     * 读取文件
+     *
+     * @param path 文件路径
+     */
+    public List<Map<String, String>> readFile(Path path) throws Exception {
+        log.info("读取: {}", path);
+        List<String> headers = Stream.of("shen_qing_dan_hao", "pai_qian_dan_hao", "shen_qing_lei_xing",
+                "che_pai_hao", "che_liang_lei_xing", "che_liang_ji_bie", "si_ji_ming_cheng", "yong_che_ren",
+                "yong_che_bu_men", "yong_che_shi_you", "chu_fa_di", "mu_di_di", "chu_fa_shi_jian", "gui_dui_shi_jian",
+                "xing_shi_li_cheng", "chu_che_shi_chang").toList();
+        try (InputStream inputStream = Files.newInputStream(path);
+             Workbook workbook = new XSSFWorkbook(inputStream)
+        ) {
+            List<Map<String, String>> resultList = new ArrayList<>();
+            // 读取第一个工作表
+            Sheet sheet = workbook.getSheetAt(0);
+            // 表头行
+            Row headerRow = sheet.getRow(0);
+            // 列数
+            int columnCount = headerRow.getPhysicalNumberOfCells();
+            log.info("columnCount: {}", columnCount);
+            // 最后行数
+            int lastRowNum = sheet.getLastRowNum();
+            log.info("lastRowNum: {}", lastRowNum);
+            if (lastRowNum == 0) {
+                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+            }
+            // 遍历行
+            for (int i = 1; i <= lastRowNum; i++) {
+                Row row = sheet.getRow(i);
+                if (row == null) {
+                    continue;
+                }
+                Map<String, String> rowMap = new LinkedHashMap<>();
+                // 遍历列
+                for (int j = 0; j < columnCount; j++) {
+                    String header = headers.get(j);
+                    String cellValue = "";
+                    rowMap.put(header, cellValue);
+                    Cell cell = row.getCell(j);
+                    if (cell == null) {
+                        continue;
+                    }
+                    switch (cell.getCellType()) {
+                        case STRING:
+                            boolean skipTrim = "chu_fa_shi_jian".equals(header)
+                                    || "gui_dui_shi_jian".equals(header);
+                            // 删除字符串空白字符
+                            cellValue = skipTrim ? cell.getStringCellValue()
+                                    : org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+                            break;
+                        case NUMERIC:
+                            if (DateUtil.isCellDateFormatted(cell)) {
+                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+                                break;
+                            }
+                            cellValue = String.valueOf(cell.getNumericCellValue());
+                            break;
+                        case BOOLEAN:
+                            cellValue = String.valueOf(cell.getBooleanCellValue());
+                            break;
+                        default:
+                            break;
+                    }
+                    rowMap.put(headers.get(j), cellValue);
+                }
+                filter1(resultList, rowMap);
+            }
+            return resultList;
+        }
+    }
+
+    public void filter1(List<Map<String, String>> list, Map<String, String> map) {
+        String yongCheShiYou = Objects.requireNonNullElse(map.get("yong_che_shi_you"), "");
+        String muDiDi = Objects.requireNonNullElse(map.get("mu_di_di"), "");
+        boolean flag = (StringUtils.containsAny(yongCheShiYou, "出差", "开会", "会议", "接站",
+                "培训", "送站", "送机", "接站", "接人", "机场", "站")
+                || StringUtils.containsAny(muDiDi, "出差", "开会", "会议", "接站", "培训", "送站",
+                "送机", "接站", "接人", "机场", "站"))
+                && !StringUtils.containsAny(yongCheShiYou, "障", "营销", "查", "物料", "省公司",
+                "省分", "集团", "勘察", "调研", "审计", "巡", "调测", "维护", "修", "处理", "设备", "客户", "交流", "办事",
+                "访", "政府", "市委", "委员会", "县委", "基站", "收费站", "公交站", "加油站", "服务站", "检查站", "街", "路",
+                "检测站", "液化气站", "总部", "省委", "党建", "机房", "调", "安装", "领导")
+                && !StringUtils.containsAny(muDiDi, "障", "营销", "查", "物料", "省公司",
+                "省分", "集团", "勘察", "调研", "审计", "巡", "调测", "维护", "修", "处理", "设备", "客户", "交流", "办事",
+                "访", "政府", "市委", "委员会", "县委", "基站", "收费站", "公交站", "加油站", "服务站", "检查站", "街", "路",
+                "检测站", "液化气站", "总部", "省委", "党建", "机房", "调", "安装", "领导");
+        if (flag) {
+            list.add(map);
+        }
+    }
+
+    /**
+     * 数据加工
+     *
+     * @param path 文件路径
+     * @param list 数据
+     */
+    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+        Integer yearMonth = 202402;
+        List<Map<String, String>> staffs = carGongCheShouFeiDao.getStaffs(yearMonth);
+        Set<String> specialCar = carGongCheShouFeiDao.getSpecialCar();
+        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+        List<AreaPo> cities = areaService.getCities();
+        List<AreaPo> districts = areaService.getDistricts();
+        Map<String, AreaPo> areaMap = areaService.getAreaMap(cities, districts);
+        Map<String, List<AreaPo>> districtListMap = areaService.getDistrictListMap(cities, districts);
+        List<Map<String, String>> resultList = new ArrayList<>();
+        for (Map<String, String> map : list) {
+//            String shenQingYongCheShiJian = map.get("shen_qing_yong_che_shi_jian");
+//            LocalDateTime localDateTime = LocalDateTime.parse(shenQingYongCheShiJian, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+//            String yearMonth = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
+//            String year = String.valueOf(localDateTime.getYear());
+//            String month = String.valueOf(localDateTime.getMonthValue());
+//            map.put("year_month", yearMonth);
+//            map.put("year_no", year);
+//            map.put("month_no", month);
+            String chuCheShiChang = map.get("chu_che_shi_chang");
+            String chuCheShiChangSeconds = String.valueOf(durationStrToSeconds(chuCheShiChang));
+            map.put("chu_che_shi_chang_seconds", chuCheShiChangSeconds);
+            String rawChePaiHao = map.get("che_pai_hao");
+//            map.put("raw_che_pai_hao", rawChePaiHao);
+            String chePaiHao = carService.getChePai(rawChePaiHao);
+            map.put("che_pai_hao", chePaiHao);
+//            String chePaiFail = carService.chePaiFail(rawChePaiHao);
+//            map.put("che_pai_fail", chePaiFail);
+            String yongCheBuMen = map.get("yong_che_bu_men");
+            String firstUnit = carService.getFirstUnit(yongCheBuMen);
+            map.put("first_unit", firstUnit);
+            String secondUnit = carService.getSecondUnit(yongCheBuMen, firstUnit);
+            map.put("second_unit", secondUnit);
+            String thirdUnit = carService.getThirdUnit(yongCheBuMen, secondUnit);
+            map.put("third_unit", thirdUnit);
+//            String areaNo = carService.getAreaNo(secondOrgs, yongCheDanWei);
+//            map.put("area_no", areaNo);
+//            String areaName = carService.getOrgName(orgMap, areaNo);
+//            map.put("area_name", areaName);
+//            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, yongCheDanWei);
+//            map.put("city_no", cityNo);
+//            String cityName = carService.getOrgName(orgMap, cityNo);
+//            map.put("city_name", cityName);
+//            String areaNo2 = carService.getAreaNo2(areaName, cityName);
+//            map.put("area_no2", areaNo2);
+//            String areaName2 = carService.getOrgName(orgMap, areaNo2);
+//            map.put("area_name2", areaName2);
+//            String cityId = carService.getCityId(cities, yongCheDanWei);
+//            map.put("city_id", cityId);
+//            String city = carService.getAreaName(areaMap, cityId);
+//            map.put("city", city);
+//            String districtId = carService.getDistrictId(districtListMap, cityId, cityName, yongCheDanWei);
+//            map.put("district_id", districtId);
+//            String district = carService.getAreaName(areaMap, districtId);
+//            map.put("district", district);
+//            map.put("source", path.getFileName().toString());
+            filter2(resultList, map, specialCar, staffs);
+        }
+        return resultList;
+    }
+
+    public void filter2(List<Map<String, String>> list, Map<String, String> map, Set<String> specialCar,
+                        List<Map<String, String>> staffs) {
+//        String xingShiLiCheng = Objects.requireNonNullElse(map.get("xing_shi_li_cheng"), "");
+//        String chuCheShiChangSeconds = Objects.requireNonNullElse(map.get("chu_che_shi_chang_seconds"), "");
+        String yongCheShiYou = Objects.requireNonNullElse(map.get("yong_che_shi_you"), "");
+        String yongCheRen = Objects.requireNonNullElse(map.get("yong_che_ren"), "");
+        String chePaiHao = Objects.requireNonNullElse(map.get("che_pai_hao"), "");
+        String firstUnit1 = Objects.requireNonNullElse(map.get("first_unit"), "");
+        boolean notInStaffs = true;
+        for (Map<String, String> staff : staffs) {
+            String firstUnit2 = staff.get("first_unit");
+            String xingMing = staff.get("xing_ming");
+            // 用车人或用车事由包含交通补贴人员且单位相同
+            if (firstUnit1.equals(firstUnit2)
+                    && (yongCheRen.replaceAll("[^一-龥]", "").equals(xingMing)
+                    || yongCheShiYou.contains(xingMing))) {
+                notInStaffs = false;
+                break;
+            }
+        }
+        if (notInStaffs) {
+            return;
+        }
+        if (specialCar.contains(chePaiHao)) {
+            log.info("特殊车辆: {}", chePaiHao);
+            return;
+        }
+//        if (new BigDecimal(chuCheShiChangSeconds).compareTo(new BigDecimal("600")) < 0
+//                || new BigDecimal(xingShiLiCheng).compareTo(BigDecimal.ZERO) = 0
+//                || new BigDecimal(xingShiLiCheng).compareTo(new BigDecimal("20")) >= 0) {
+//            return;
+//        }
+        list.add(map);
+    }
+
+    /**
+     * 生成csv
+     *
+     * @param path 源文件路径
+     * @param list 数据
+     */
+    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+        log.info("条数:{}", list.size());
+        Files.createDirectories(Paths.get("test/history/"));
+        Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv");
+        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+                StandardCharsets.UTF_8);
+             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+            // 添加bom头避免excel乱码
+            osw.write('\ufeff');
+//            Map<String, String> header = list.get(0);
+//            // 表头
+//            printer.printRecord(header.keySet());
+            printer.printRecord("申请单号", "派遣单号", "申请类型", "车牌号", "车辆类型", "车辆级别", "司机名称", "用车人", "用车部门", "用车事由", "出发地", "目的地", "出发时间", "归队时间", "行驶里程", "出车时长", "出车时长秒", "用车单位一级", "用车单位二级", "用车单位三级");
+            for (Map<String, String> map : list) {
+                printer.printRecord(
+                        map.get("shen_qing_dan_hao"),
+                        map.get("pai_qian_dan_hao"),
+                        map.get("shen_qing_lei_xing"),
+                        map.get("che_pai_hao"),
+                        map.get("che_liang_lei_xing"),
+                        map.get("che_liang_ji_bie"),
+                        map.get("si_ji_ming_cheng"),
+                        map.get("yong_che_ren"),
+                        map.get("yong_che_bu_men"),
+                        map.get("yong_che_shi_you"),
+                        map.get("chu_fa_di"),
+                        map.get("mu_di_di"),
+                        map.get("chu_fa_shi_jian"),
+                        map.get("gui_dui_shi_jian"),
+                        map.get("xing_shi_li_cheng"),
+                        map.get("chu_che_shi_chang"),
+                        map.get("chu_che_shi_chang_seconds"),
+                        map.get("first_unit"),
+                        map.get("second_unit"),
+                        map.get("third_unit")
+                );
+            }
+        }
+        return csvPath;
+    }
+
+    /**
+     * 时长字符串转秒数
+     * @param durationStr 时长字符串
+     */
+    public long durationStrToSeconds(String durationStr) {
+        if (StringUtils.isEmpty(durationStr) || "0".equals(durationStr)) {
+            return 0;
+        }
+        // 定义正则表达式,匹配时分秒、分钟秒和秒三种格式
+        String regex = "(\\d+时)?(\\d+分)?(\\d+秒)";
+
+        // 使用Pattern和Matcher进行匹配
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(durationStr);
+
+        // 检查是否匹配成功
+        if (!matcher.matches()) {
+            return 0;
+        }
+
+        // 提取时、分、秒的数值
+        long hours = 0;
+        long minutes = 0;
+        long seconds;
+
+        // 根据匹配到的组数确定时、分、秒的值
+        if (matcher.group(1) != null) {
+            hours = Long.parseLong(matcher.group(1).substring(0, matcher.group(1).length() - 1));
+        }
+        if (matcher.group(2) != null) {
+            minutes = Long.parseLong(matcher.group(2).substring(0, matcher.group(2).length() - 1));
+        }
+        seconds = Long.parseLong(matcher.group(3).substring(0, matcher.group(3).length() - 1));
+
+        // 将时、分、秒转换为总秒数
+        return hours * 3600L + minutes * 60L + seconds;
+    }
+}

+ 203 - 0
src/test/java/com/nokia/finance/tasks/car/CarJiaoTongBuTieTests.java

@@ -0,0 +1,203 @@
+package com.nokia.finance.tasks.car;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+import com.nokia.finance.tasks.service.car.CarService;
+import com.nokia.finance.tasks.service.common.OrganizationService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.util.CollectionUtils;
+
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class CarJiaoTongBuTieTests {
+    @Autowired
+    CarService carService;
+    @Autowired
+    OrganizationService organizationService;
+
+    /**
+     * 执行任务
+     */
+    @Test
+    void runJob() {
+        // 数据目录
+        Path dir = Paths.get("test/data/jiao-tong-bu-tie");
+        try (Stream<Path> stream = Files.list(dir)) {
+            // 获取数据目录下的文件列表
+            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+            log.info("数据文件列表: {}", pathList);
+            if (CollectionUtils.isEmpty(pathList)) {
+                throw new MyRuntimeException("没有文件");
+            }
+            for (Path path : pathList) {
+                singleJob(path);
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 处理单个文件
+     *
+     * @param path 文件路径
+     */
+    public void singleJob(Path path) throws Exception {
+        List<Map<String, String>> list = readFile(path);
+        List<Map<String, String>> distinctList = dataProcessing(path, list);
+        Path csvPath = toCsv(path, distinctList);
+    }
+
+    /**
+     * 读取文件
+     *
+     * @param path 文件路径
+     */
+    public List<Map<String, String>> readFile(Path path) throws Exception {
+        log.info("读取: {}", path);
+        List<String> headers = Stream.of("year_month","di_shi","bu_men","yuan_gong_bian_hao","xing_ming")
+                .toList();
+        try (InputStream inputStream = Files.newInputStream(path);
+             Workbook workbook = new XSSFWorkbook(inputStream)
+        ) {
+            List<Map<String, String>> resultList = new ArrayList<>();
+            // 读取第一个工作表
+            Sheet sheet = workbook.getSheetAt(0);
+            // 表头行
+            Row headerRow = sheet.getRow(0);
+            // 列数
+            int columnCount = headerRow.getPhysicalNumberOfCells();
+            log.info("columnCount: {}", columnCount);
+            // 最后行数
+            int lastRowNum = sheet.getLastRowNum();
+            log.info("lastRowNum: {}", lastRowNum);
+            if (lastRowNum == 0) {
+                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+            }
+            // 遍历行
+            for (int i = 1; i <= lastRowNum; i++) {
+                Row row = sheet.getRow(i);
+                if (row == null) {
+                    continue;
+                }
+                Map<String, String> rowMap = new LinkedHashMap<>();
+                // 遍历列
+                for (int j = 0; j < columnCount; j++) {
+                    String header = headers.get(j);
+                    String cellValue = "";
+                    rowMap.put(header, cellValue);
+                    Cell cell = row.getCell(j);
+                    if (cell == null) {
+                        continue;
+                    }
+                    switch (cell.getCellType()) {
+                        case STRING:
+                            // 删除字符串空白字符
+                            cellValue = org.springframework.util.StringUtils.trimAllWhitespace(cell.getStringCellValue());
+                            break;
+                        case NUMERIC:
+                            if (DateUtil.isCellDateFormatted(cell)) {
+                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+                                break;
+                            }
+                            cellValue = String.valueOf(cell.getNumericCellValue());
+                            break;
+                        case BOOLEAN:
+                            cellValue = String.valueOf(cell.getBooleanCellValue());
+                            break;
+                        default:
+                            break;
+                    }
+                    rowMap.put(headers.get(j), cellValue);
+                }
+                resultList.add(rowMap);
+            }
+            return resultList;
+        }
+    }
+
+    /**
+     * 数据加工
+     *
+     * @param path 文件路径
+     * @param list 数据
+     */
+    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+        for (Map<String, String> map : list) {
+            String buMen = map.get("bu_men");
+            String firstUnit = carService.getFirstUnit(buMen);
+            map.put("first_unit", firstUnit);
+            String secondUnit = carService.getSecondUnit(buMen, firstUnit);
+            map.put("second_unit", secondUnit);
+            String thirdUnit = carService.getThirdUnit(buMen, secondUnit);
+            map.put("third_unit", thirdUnit);
+            String areaNo = carService.getAreaNo(secondOrgs, buMen);
+            map.put("area_no", areaNo);
+            String areaName = carService.getOrgName(orgMap, areaNo);
+            map.put("area_name", areaName);
+            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, buMen);
+            map.put("city_no", cityNo);
+            String cityName = carService.getOrgName(orgMap, cityNo);
+            map.put("city_name", cityName);
+            map.put("source", path.getFileName().toString());
+        }
+        return list;
+    }
+
+    /**
+     * 生成csv
+     *
+     * @param path 源文件路径
+     * @param list 数据
+     */
+    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+        log.info("条数:{}", list.size());
+        Files.createDirectories(Paths.get("test/history/"));
+        Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv");
+        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+                StandardCharsets.UTF_8);
+             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+            // 添加bom头避免excel乱码
+            osw.write('\ufeff');
+            Map<String, String> header = list.get(0);
+            // 表头
+            printer.printRecord(header.keySet());
+            for (Map<String, String> map : list) {
+                printer.printRecord(map.values());
+            }
+        }
+        return csvPath;
+    }
+}

+ 407 - 0
src/test/java/com/nokia/finance/tasks/car/CarLianXuJiaYouTests.java

@@ -0,0 +1,407 @@
+package com.nokia.finance.tasks.car;
+
+import com.nokia.finance.tasks.common.exception.MyRuntimeException;
+import com.nokia.finance.tasks.pojo.po.common.AreaPo;
+import com.nokia.finance.tasks.pojo.po.common.OrganizationPo;
+import com.nokia.finance.tasks.service.car.CarService;
+import com.nokia.finance.tasks.service.common.AreaService;
+import com.nokia.finance.tasks.service.common.OrganizationService;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class CarLianXuJiaYouTests {
+    @Autowired
+    CarService carService;
+    @Autowired
+    OrganizationService organizationService;
+    @Autowired
+    AreaService areaService;
+
+    /**
+     * 执行任务
+     */
+    @Test
+    void runJob() {
+        // 数据目录
+        Path dir = Paths.get("test/data/lian-xu-jia-you");
+        try (Stream<Path> stream = Files.list(dir)) {
+            // 获取数据目录下的文件列表
+            List<Path> pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList();
+            log.info("数据文件列表: {}", pathList);
+            if (CollectionUtils.isEmpty(pathList)) {
+                throw new MyRuntimeException("没有文件");
+            }
+            for (Path path : pathList) {
+                singleJob(path);
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 处理单个文件
+     *
+     * @param path 文件路径
+     */
+    public void singleJob(Path path) throws Exception {
+        List<Map<String, String>> list = readFile(path);
+        List<Map<String, String>> distinctList = dataProcessing(path, list);
+        Path csvPath = toCsv(path, distinctList);
+    }
+
+    /**
+     * 读取文件
+     *
+     * @param path 文件路径
+     */
+    public List<Map<String, String>> readFile(Path path) throws Exception {
+        log.info("读取: {}", path);
+        List<String> headers = Stream.of("shen_qing_dan_hao", "shen_qing_dan_ming_cheng", "bao_zhang_shi_jian",
+                "di_shi", "shen_qing_ren", "ka_hao", "che_pai_hao", "jiao_yi_shi_jian", "bu_han_shui_jin_e", "shui_lv",
+                "shui_e", "jia_shui_he_ji_jin_e", "che_liang_suo_shu_dan_wei", "di_dian").toList();
+        try (InputStream inputStream = Files.newInputStream(path);
+             Workbook workbook = new XSSFWorkbook(inputStream)
+        ) {
+            List<Map<String, String>> resultList = new ArrayList<>();
+            // 读取第一个工作表
+            Sheet sheet = workbook.getSheetAt(0);
+            // 表头行
+            Row headerRow = sheet.getRow(0);
+            // 列数
+            int columnCount = headerRow.getPhysicalNumberOfCells();
+            log.info("columnCount: {}", columnCount);
+            // 最后行数
+            int lastRowNum = sheet.getLastRowNum();
+            log.info("lastRowNum: {}", lastRowNum);
+            if (lastRowNum == 0) {
+                throw new MyRuntimeException(path.getFileName() + " 数据0条");
+            }
+            // 遍历行
+            for (int i = 1; i <= lastRowNum; i++) {
+                Row row = sheet.getRow(i);
+                if (row == null) {
+                    continue;
+                }
+                Map<String, String> rowMap = new LinkedHashMap<>();
+                // 遍历列
+                for (int j = 0; j < columnCount; j++) {
+                    String header = headers.get(j);
+                    String cellValue = "";
+                    rowMap.put(header, cellValue);
+                    Cell cell = row.getCell(j);
+                    if (cell == null) {
+                        continue;
+                    }
+                    switch (cell.getCellType()) {
+                        case STRING:
+                            boolean skipTrim = "bao_zhang_shi_jian".equals(header) || "jiao_yi_shi_jian".equals(header);
+                            // 删除字符串空白字符
+                            cellValue = skipTrim ? cell.getStringCellValue()
+                                    : StringUtils.trimAllWhitespace(cell.getStringCellValue());
+                            break;
+                        case NUMERIC:
+                            if (DateUtil.isCellDateFormatted(cell)) {
+                                cellValue = DateUtil.getLocalDateTime(cell.getNumericCellValue())
+                                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
+                                break;
+                            }
+                            cellValue = String.valueOf(cell.getNumericCellValue());
+                            break;
+                        case BOOLEAN:
+                            cellValue = String.valueOf(cell.getBooleanCellValue());
+                            break;
+                        default:
+                            break;
+                    }
+                    rowMap.put(headers.get(j), cellValue);
+                }
+                resultList.add(rowMap);
+            }
+            return resultList;
+        }
+    }
+
+    /**
+     * 数据加工
+     *
+     * @param path 文件路径
+     * @param list 数据
+     */
+    public List<Map<String, String>> dataProcessing(Path path, List<Map<String, String>> list) {
+        List<OrganizationPo> secondOrgs = organizationService.getSecondOrgs();
+        List<OrganizationPo> thirdOrgs = organizationService.getThirdOrgs();
+        Map<String, OrganizationPo> orgMap = organizationService.getOrgMap(secondOrgs, thirdOrgs);
+        Map<String, List<OrganizationPo>> thirdOrganizationListMap =
+                organizationService.getThirdOrganizationListMap(secondOrgs, thirdOrgs);
+        List<AreaPo> cities = areaService.getCities();
+        List<AreaPo> districts = areaService.getDistricts();
+        Map<String, AreaPo> areaMap = areaService.getAreaMap(cities, districts);
+        Map<String, List<AreaPo>> districtListMap = areaService.getDistrictListMap(cities, districts);
+        // 按车牌号分组
+        Map<String, List<CarLianXuJiaYouBo>> carLianXuJiaYouMap = new HashMap<>();
+        for (Map<String, String> map : list) {
+            String jiaoYiShiJian = map.get("jiao_yi_shi_jian");
+            LocalDateTime localDateTime = LocalDateTime.parse(jiaoYiShiJian, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            String jiaoYiDate = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            String yearMonth = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
+            String year = String.valueOf(localDateTime.getYear());
+            String month = String.valueOf(localDateTime.getMonthValue());
+            map.put("jiao_yi_date", jiaoYiDate);
+            map.put("year_month", yearMonth);
+            map.put("year_no", year);
+            map.put("month_no", month);
+            String rawChePaiHao = map.get("che_pai_hao");
+            map.put("raw_che_pai_hao", rawChePaiHao);
+            String chePaiHao = carService.getChePai(rawChePaiHao);
+            map.put("che_pai_hao", chePaiHao);
+            String chePaiFail = carService.chePaiFail(rawChePaiHao);
+            map.put("che_pai_fail", chePaiFail);
+            String cheLiangSuoShuDanWei = map.get("che_liang_suo_shu_dan_wei");
+            String firstUnit = carService.getFirstUnit(cheLiangSuoShuDanWei);
+            map.put("first_unit", firstUnit);
+            String secondUnit = carService.getSecondUnit(cheLiangSuoShuDanWei, firstUnit);
+            map.put("second_unit", secondUnit);
+            String thirdUnit = carService.getThirdUnit(cheLiangSuoShuDanWei, secondUnit);
+            map.put("third_unit", thirdUnit);
+            String areaNo = carService.getAreaNo(secondOrgs, cheLiangSuoShuDanWei);
+            map.put("area_no", areaNo);
+            String areaName = carService.getOrgName(orgMap, areaNo);
+            map.put("area_name", areaName);
+            String cityNo = carService.getCityNo(thirdOrganizationListMap, areaNo, areaName, cheLiangSuoShuDanWei);
+            map.put("city_no", cityNo);
+            String cityName = carService.getOrgName(orgMap, cityNo);
+            map.put("city_name", cityName);
+            String areaNo2 = carService.getAreaNo2(areaName, cityName);
+            map.put("area_no2", areaNo2);
+            String areaName2 = carService.getOrgName(orgMap, areaNo2);
+            map.put("area_name2", areaName2);
+            String cityId = carService.getCityId(cities, cheLiangSuoShuDanWei);
+            map.put("city_id", cityId);
+            String city = carService.getAreaName(areaMap, cityId);
+            map.put("city", city);
+            String districtId = carService.getDistrictId(districtListMap, cityId, cityName, cheLiangSuoShuDanWei);
+            map.put("district_id", districtId);
+            String district = carService.getAreaName(areaMap, districtId);
+            map.put("district", district);
+            map.put("source", path.getFileName().toString());
+            carLianXuJiaYouMap.putIfAbsent(chePaiHao, new ArrayList<>());
+            List<CarLianXuJiaYouBo> carLianXuJiaYouBoList = carLianXuJiaYouMap.get(chePaiHao);
+            carLianXuJiaYouBoList.add(new CarLianXuJiaYouBo(map, localDateTime));
+        }
+        List<CarLianXuJiaYouBo> result = new ArrayList<>();
+        for (List<CarLianXuJiaYouBo> l1 : carLianXuJiaYouMap.values()) {
+            List<CarLianXuJiaYouBo> l2 = l1.stream()
+                    .sorted(Comparator.comparing(CarLianXuJiaYouBo::getLocalDateTime)).toList();
+            result.addAll(l2);
+            int size = l2.size() - 1;
+            for (int i = 0; i < size; i++) {
+                CarLianXuJiaYouBo t1 = l2.get(i);
+                CarLianXuJiaYouBo t2 = l2.get(i + 1);
+                Duration duration = Duration.between(t1.getLocalDateTime(), t2.getLocalDateTime());
+                long hours = duration.toHours();
+                if (hours <= 48) {
+                    t1.setNextJiaoYiShiJian(t2.getJiaoYiShiJian());
+                    t1.setNextJiaoYiDate(t2.getJiaoYiDate());
+                    t1.setNextBuHanShuiJinE(t2.getBuHanShuiJinE());
+                    long seconds = duration.toSeconds();
+                    t1.setTimeInterval(String.valueOf(seconds));
+                    BigDecimal n1 = new BigDecimal(Objects.requireNonNull(t1.getBuHanShuiJinE(), "0"));
+                    BigDecimal n2 = new BigDecimal(Objects.requireNonNull(t2.getBuHanShuiJinE(), "0"));
+                    t1.setBuHanShuiJinESum(n1.add(n2).toString());
+                }
+            }
+        }
+        return result.stream().map(CarLianXuJiaYouBo::toMap).toList();
+    }
+
+    /**
+     * 生成csv
+     *
+     * @param path 源文件路径
+     * @param list 数据
+     */
+    public Path toCsv(Path path, List<Map<String, String>> list) throws Exception {
+        log.info("条数:{}", list.size());
+        Files.createDirectories(Paths.get("test/history/"));
+        Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv");
+        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath),
+                StandardCharsets.UTF_8);
+             CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) {
+            // 添加bom头避免excel乱码
+            osw.write('\ufeff');
+            Map<String, String> header = list.get(0);
+            // 表头
+            printer.printRecord(header.keySet());
+            for (Map<String, String> map : list) {
+                printer.printRecord(map.values());
+            }
+        }
+        return csvPath;
+    }
+
+    @NoArgsConstructor
+    @Data
+    static class CarLianXuJiaYouBo {
+
+        private String shenQingDanHao;
+        private String shenQingDanMingCheng;
+        private String baoZhangShiJian;
+        private String diShi;
+        private String shenQingRen;
+        private String kaHao;
+        private String chePaiHao;
+        private String jiaoYiShiJian;
+        private String buHanShuiJinE;
+        private String shuiLv;
+        private String shuiE;
+        private String jiaShuiHeJiJinE;
+        private String cheLiangSuoShuDanWei;
+        private String diDian;
+        private String jiaoYiDate;
+        private String yearMonth;
+        private String yearNo;
+        private String monthNo;
+        private String rawChePaiHao;
+        private String chePaiFail;
+        private String firstUnit;
+        private String secondUnit;
+        private String thirdUnit;
+        private String areaNo;
+        private String areaName;
+        private String cityNo;
+        private String cityName;
+        private String areaNo2;
+        private String areaName2;
+        private String cityId;
+        private String city;
+        private String districtId;
+        private String district;
+        private String source;
+        private LocalDateTime localDateTime;
+        private String nextJiaoYiShiJian;
+        private String nextJiaoYiDate;
+        private String nextBuHanShuiJinE;
+        private String timeInterval;
+        private String buHanShuiJinESum;
+
+        public CarLianXuJiaYouBo(Map<String, String> map, LocalDateTime localDateTime) {
+            this.shenQingDanHao = map.get("shen_qing_dan_hao");
+            this.shenQingDanMingCheng = map.get("shen_qing_dan_ming_cheng");
+            this.baoZhangShiJian = map.get("bao_zhang_shi_jian");
+            this.diShi = map.get("di_shi");
+            this.shenQingRen = map.get("shen_qing_ren");
+            this.kaHao = map.get("ka_hao");
+            this.chePaiHao = map.get("che_pai_hao");
+            this.jiaoYiShiJian = map.get("jiao_yi_shi_jian");
+            this.buHanShuiJinE = map.get("bu_han_shui_jin_e");
+            this.shuiLv = map.get("shui_lv");
+            this.shuiE = map.get("shui_e");
+            this.jiaShuiHeJiJinE =map.get("jia_shui_he_ji_jin_e");
+            this.cheLiangSuoShuDanWei = map.get("che_liang_suo_shu_dan_wei");
+            this.diDian = map.get("di_dian");
+            this.jiaoYiDate = map.get("jiao_yi_date");
+            this.yearMonth = map.get("year_month");
+            this.yearNo = map.get("year_no");
+            this.monthNo = map.get("month_no");
+            this.rawChePaiHao = map.get("raw_che_pai_hao");
+            this.chePaiFail = map.get("che_pai_fail");
+            this.firstUnit = map.get("first_unit");
+            this.secondUnit = map.get("second_unit");
+            this.thirdUnit = map.get("third_unit");
+            this.areaNo = map.get("area_no");
+            this.areaName = map.get("area_name");
+            this.cityNo = map.get("city_no");
+            this.cityName = map.get("city_name");
+            this.areaNo2 = map.get("area_no2");
+            this.areaName2 = map.get("area_name2");
+            this.cityId = map.get("city_id");
+            this.city = map.get("city");
+            this.districtId = map.get("district_id");
+            this.district = map.get("district");
+            this.source = map.get("source");
+            this.localDateTime = localDateTime;
+        }
+
+        public Map<String, String> toMap() {
+            LinkedHashMap<String, String> map = new LinkedHashMap<>();
+            map.put("shen_qing_dan_hao", shenQingDanHao);
+            map.put("shen_qing_dan_ming_cheng", shenQingDanMingCheng);
+            map.put("bao_zhang_shi_jian", baoZhangShiJian);
+            map.put("di_shi", diShi);
+            map.put("shen_qing_ren", shenQingRen);
+            map.put("ka_hao", kaHao);
+            map.put("che_pai_hao", chePaiHao);
+            map.put("jiao_yi_shi_jian", jiaoYiShiJian);
+            map.put("bu_han_shui_jin_e", buHanShuiJinE);
+            map.put("shui_lv", shuiLv);
+            map.put("shui_e", shuiE);
+            map.put("jia_shui_he_ji_jin_e", jiaShuiHeJiJinE);
+            map.put("che_liang_suo_shu_dan_wei", cheLiangSuoShuDanWei);
+            map.put("di_dian", diDian);
+            map.put("jiao_yi_date", jiaoYiDate);
+            map.put("year_month", yearMonth);
+            map.put("year_no", yearNo);
+            map.put("month_no", monthNo);
+            map.put("raw_che_pai_hao", rawChePaiHao);
+            map.put("che_pai_fail", chePaiFail);
+            map.put("first_unit", firstUnit);
+            map.put("second_unit", secondUnit);
+            map.put("third_unit", thirdUnit);
+            map.put("area_no", areaNo);
+            map.put("area_name", areaName);
+            map.put("city_no", cityNo);
+            map.put("city_name", cityName);
+            map.put("area_no2", areaNo2);
+            map.put("area_name2", areaName2);
+            map.put("city_id", cityId);
+            map.put("city", city);
+            map.put("district_id", districtId);
+            map.put("district", district);
+            map.put("source", source);
+            map.put("next_jiao_yi_shi_jian", nextJiaoYiShiJian);
+            map.put("next_jiao_yi_date", nextJiaoYiDate);
+            map.put("next_bu_han_shui_jin_e", nextBuHanShuiJinE);
+            map.put("time_interval", timeInterval);
+            map.put("bu_han_shui_jin_e_sum", buHanShuiJinESum);
+            return map;
+        }
+    }
+}

+ 50 - 0
src/test/java/com/nokia/finance/tasks/car/CarStrategyJobTests.java

@@ -0,0 +1,50 @@
+package com.nokia.finance.tasks.car;
+
+import com.nokia.finance.tasks.jobs.car.cxdp.CarCxdpJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarHighFuelConsumptionJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarHighRepairJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarInefficiencyPercentJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarInefficiencyQxJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarRentalRepairJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarViolationUnprocessedJob;
+import com.nokia.finance.tasks.jobs.car.strategy.CarWdyjJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class CarStrategyJobTests {
+    @Autowired
+    CarWdyjJob carWdyjJob;
+    @Autowired
+    CarHighFuelConsumptionJob carHighFuelConsumptionJob;
+    @Autowired
+    CarHighRepairJob carHighRepairJob;
+    @Autowired
+    CarInefficiencyPercentJob carInefficiencyPercentJob;
+    @Autowired
+    CarInefficiencyQxJob carInefficiencyQxJob;
+    @Autowired
+    CarRentalRepairJob carRentalRepairJob;
+    @Autowired
+    CarViolationUnprocessedJob carViolationUnprocessedJob;
+    @Autowired
+    CarCxdpJob carCxdpJob;
+
+    @Test
+    void runJobTest() {
+//        carWdyjJob.runJob();
+//        carHighFuelConsumptionJob.runJob();
+//        carHighRepairJob.runJob();
+//        carInefficiencyPercentJob.runJob();
+//        carInefficiencyQxJob.runJob();
+//        carRentalRepairJob.runJob();
+//        carViolationUnprocessedJob.runJob();
+        carCxdpJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/car/procedure/CarBaseDataMonthProcJobTests.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.car.procedure;
+
+import com.nokia.finance.tasks.jobs.car.procedure.CarBaseDataMonthProcJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class CarBaseDataMonthProcJobTests {
+    @Autowired
+    CarBaseDataMonthProcJob carBaseDataMonthProcJob;
+
+    @Test
+    void runJobTest() {
+        carBaseDataMonthProcJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/car/procedure/CarFeeProcJobTests.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.car.procedure;
+
+import com.nokia.finance.tasks.jobs.car.procedure.CarFeeProcJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("prod")
+class CarFeeProcJobTests {
+    @Autowired
+    CarFeeProcJob carFeeProcJob;
+
+    @Test
+    void runJobTest() {
+        carFeeProcJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/car/procedure/CarLiChengMonthProcJobTests.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.car.procedure;
+
+import com.nokia.finance.tasks.jobs.car.procedure.CarLiChengMonthProcJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("prod")
+class CarLiChengMonthProcJobTests {
+    @Autowired
+    CarLiChengMonthProcJob carLiChengMonthProcJob;
+
+    @Test
+    void runJobTest() {
+        carLiChengMonthProcJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/car/procedure/CarPaiDanProcJobTests.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.car.procedure;
+
+import com.nokia.finance.tasks.jobs.car.procedure.CarPaiDanProcJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class CarPaiDanProcJobTests {
+    @Autowired
+    CarPaiDanProcJob carPaiDanProcJob;
+
+    @Test
+    void runJobTest() {
+        carPaiDanProcJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/car/ruixing/CarYongCheZongLanJobTests.java

@@ -0,0 +1,22 @@
+//package com.nokia.finance.tasks.car.ruixing;
+//
+//import com.nokia.finance.tasks.jobs.car.ruixing.CarYongCheZongLanJob;
+//import lombok.extern.slf4j.Slf4j;
+//import org.junit.jupiter.api.Test;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//import org.springframework.test.context.ActiveProfiles;
+//
+//@Slf4j
+//@SpringBootTest
+//@ActiveProfiles("dev")
+//class CarYongCheZongLanJobTests {
+//    @Autowired
+//    CarYongCheZongLanJob carYongCheZongLanJob;
+//
+//    @Test
+//    void runJobTest() {
+//        carYongCheZongLanJob.runJob();
+//    }
+//
+//}

+ 30 - 0
src/test/java/com/nokia/finance/tasks/house/fcdp/HouseFcdpJobTests.java

@@ -0,0 +1,30 @@
+package com.nokia.finance.tasks.house.fcdp;
+
+import com.nokia.finance.tasks.jobs.house.fcdp.HouseBuildingAreaStatJob;
+import com.nokia.finance.tasks.jobs.house.fcdp.HouseBuildingLandCountJob;
+import com.nokia.finance.tasks.jobs.house.fcdp.HouseRentalIncomeJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class HouseFcdpJobTests {
+    @Autowired
+    HouseBuildingAreaStatJob houseBuildingAreaStatJob;
+    @Autowired
+    HouseBuildingLandCountJob houseBuildingLandCountJob;
+    @Autowired
+    HouseRentalIncomeJob houseRentalIncomeJob;
+
+    @Test
+    void runJobTest() {
+        houseBuildingAreaStatJob.runJob();
+        houseBuildingLandCountJob.runJob();
+        houseRentalIncomeJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/house/procedure/HouseBuildingRepairProcJobTests.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.house.procedure;
+
+import com.nokia.finance.tasks.jobs.house.procedure.HouseBuildingRepairProcJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("prod")
+class HouseBuildingRepairProcJobTests {
+    @Autowired
+    HouseBuildingRepairProcJob houseBuildingRepairProcJob;
+
+    @Test
+    void runJobTest() {
+        houseBuildingRepairProcJob.runJob();
+    }
+
+}

+ 22 - 0
src/test/java/com/nokia/finance/tasks/house/strategy/HouseBuildingIdleStrategyJobTests.java

@@ -0,0 +1,22 @@
+package com.nokia.finance.tasks.house.strategy;
+
+import com.nokia.finance.tasks.jobs.house.strategy.HouseBuildingIdleStrategyJob;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class HouseBuildingIdleStrategyJobTests {
+    @Autowired
+    HouseBuildingIdleStrategyJob houseBuildingIdleStrategyJob;
+
+    @Test
+    void runJobTest() {
+        houseBuildingIdleStrategyJob.runJob();
+    }
+
+}