Forráskód Böngészése

基本复原了之前的能力

lifuquan 1 éve
szülő
commit
01fcb2e623

+ 40 - 0
doc/sql/high_quality_count_day建表.sql

@@ -0,0 +1,40 @@
+-- tsl_data.high_quality_count_day
+CREATE TABLE tsl_data.high_quality_count_day
+(
+    id                         bigserial    NOT NULL,
+    month_id                   varchar(6)   NOT NULL,
+    day_id                     varchar(2)   NOT NULL,
+    acct_date                  varchar(30)  NOT NULL,
+    businoareaname             varchar(15)  NOT NULL,
+    profes_dep                 varchar(15)  NOT NULL,
+    big_type_name              varchar(60)  NOT NULL,
+    small_type_name            varchar(120) NOT NULL,
+    total_complaints           varchar(30)  NULL,
+    hotline_complaints         varchar(30)  NULL,
+    other_complaint            varchar(30)  NULL,
+    litigation_volume          varchar(30)  NULL,
+    satisfaction_rate          varchar(30)  NULL,
+    satisfaction_count         varchar(30)  NULL,
+    total_evaluation           varchar(30)  NULL,
+    complaint_satisfied        varchar(30)  NULL,
+    complaint_satisfied_list   varchar(30)  NULL,
+    complaint_satisfied_count  varchar(30)  NULL,
+    complaint_resolution       varchar(30)  NULL,
+    complaint_resolution_list  varchar(30)  NULL,
+    complaint_resolution_count varchar(30)  NULL,
+    complaint_response         varchar(30)  NULL,
+    complaint_response_list    varchar(30)  NULL,
+    complaint_response_count   varchar(30)  NULL,
+    complaint                  varchar(30)  NULL,
+    fault_satisfaction_rate    varchar(30)  NULL,
+    fault_satisfaction_list    varchar(30)  NULL,
+    fault_satisfaction_count   varchar(30)  NULL,
+    fault_resolution_rate      varchar(30)  NULL,
+    fault_resolution_list      varchar(30)  NULL,
+    fault_resolution_count     varchar(30)  NULL,
+    fault_response_rate        varchar(30)  NULL,
+    fault_response_list        varchar(30)  NULL,
+    fault_response_count       varchar(30)  NULL,
+    cteate_time                timestamp    NULL DEFAULT now(),
+    CONSTRAINT high_quality_count_day_pkey PRIMARY KEY (id)
+);

+ 1 - 1
doc/sql/high_quality_list_day建表.sql

@@ -1,4 +1,4 @@
--- high_quality_list_day
+-- tsl_data.high_quality_list_day
 create table tsl_data.high_quality_list_day (
     id bigserial NOT NULL,
     month_id	varchar(18) NULL,

+ 54 - 0
doc/sql/mobile_complaint_day建表.sql

@@ -0,0 +1,54 @@
+-- tsl_data.mobile_complaint
+CREATE TABLE tsl_data.mobile_complaint_day
+(
+    id                     bigserial     NOT NULL,
+    month_id               varchar(6)    NOT NULL,
+    day_id                 varchar(2)    NOT NULL,
+    acct_date              varchar(300)  NOT NULL,
+    sheet_no               varchar(150)  NULL,
+    is_online_complete     varchar(300)  NULL,
+    contact_no             varchar(300)  NULL,
+    busi_no                varchar(300)  NULL,
+    serv_content           varchar(4136) NULL,
+    last_deal_content      varchar(4136) NULL,
+    deal_depart_name       varchar(300)  NULL,
+    deal_opinion           varchar(4136) NULL,
+    serv_type              varchar(600)  NULL,
+    bus_type               varchar(300)  NULL,
+    duty_reason            varchar(600)  NULL,
+    accept_channel         varchar(300)  NULL,
+    submit_channel         varchar(300)  NULL,
+    compl_area_local       varchar(300)  NULL,
+    duty_major             varchar(300)  NULL,
+    product_name           varchar(600)  NULL,
+    sp_product_code        varchar(600)  NULL,
+    pre_repair_name        varchar(300)  NULL,
+    pre_repair_charges     varchar(24)   NULL,
+    fault_location         varchar(300)  NULL,
+    cust_level             varchar(300)  NULL,
+    satisfaction_in_reply  varchar(300)  NULL,
+    is_ok_in_reply         varchar(300)  NULL,
+    accept_time            varchar(19)   NULL,
+    end_time               varchar(19)   NULL,
+    proce_time             varchar(19)   NULL,
+    cust_area              varchar(300)  NULL,
+    is_cust_serv_complete  varchar(300)  NULL,
+    is_send_sheet_complete varchar(300)  NULL,
+    is_repeat              varchar(300)  NULL,
+    is_upgrade             varchar(300)  NULL,
+    is_timeout             varchar(300)  NULL,
+    gis_city               varchar(300)  NULL,
+    process_nums           varchar(24)   NULL,
+    deal_depart_name_1     varchar(300)  NULL,
+    deal_depart_name_2     varchar(300)  NULL,
+    deal_depart_name_3     varchar(300)  NULL,
+    first_call_back_time   varchar(19)   NULL,
+    proce_remark           varchar(4136) NULL,
+    duty_major_day         varchar(300)  NULL,
+    duty_reason_id_day     varchar(300)  NULL,
+    duty_major_month       varchar(300)  NULL,
+    duty_reason_id_month   varchar(300)  NULL,
+    voice_text             varchar(4136) NULL,
+    cteate_time            timestamp     NULL DEFAULT now(),
+    CONSTRAINT mobile_complaint_pkey PRIMARY KEY (id)
+);

+ 0 - 1
src/main/java/com/nokia/tsl_data/dao/SysDataDictionaryRepository.java

@@ -23,7 +23,6 @@ public interface SysDataDictionaryRepository extends JpaRepository<SysDataDictio
         return result;
     }
 
-    // @Query("select t from SysDataDictionary t where t.typeName = 'city'")
     default List<String> findAllCityName() {
         List<String> result = new ArrayList<>();
         List<SysDataDictionary> dictionaries = findByTypeName("city");

+ 0 - 31
src/main/java/com/nokia/tsl_data/dao/TargetTsRatioMapper.java

@@ -1,31 +0,0 @@
-package com.nokia.tsl_data.dao;
-
-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.List;
-import java.util.Map;
-
-@Mapper
-public interface TargetTsRatioMapper {
-    /**
-     * 按月查询管理端目标万投率
-     */
-    @Select("select city_name, management_target_ts_ratio from report_auto.target_ts_ratio where month_id = #{monthId}")
-    List<Map<String, Object>> selectManagementTargetTsRatioForMonth(String monthId);
-
-    /**
-     * 按月查询客户端目标万投率
-     */
-    @Select("select city_name, customer_target_ts_ratio from report_auto.target_ts_ratio where month_id = #{monthId}")
-    List<Map<String, Object>> selectCustomerTargetTsRatioForMonth(String monthId);
-
-    @Select("select city_name, management_target_ts_ratio, customer_target_ts_ratio from report_auto.target_ts_ratio")
-    List<Map<String, Object>> findAll();
-
-    @Update("update report_auto.target_ts_ratio set management_target_ts_ratio = #{value} where month_id = #{monthId} and city_name = #{city}")
-    void updateManagementTargetTsRatio(@Param("monthId") String monthId, @Param("city") String city, @Param("value") double value);
-
-}

+ 4 - 0
src/main/java/com/nokia/tsl_data/dao/TargetTsRatioRepository.java

@@ -4,6 +4,10 @@ import com.nokia.tsl_data.entity.TargetTsRatio;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface TargetTsRatioRepository extends JpaRepository<TargetTsRatio, Long> {
+
+    List<TargetTsRatio> findByMonthId(String monthId);
 }

+ 26 - 3
src/main/java/com/nokia/tsl_data/dao/TslDataDao.java

@@ -113,7 +113,7 @@ public class TslDataDao {
     /**
      * high_quality_list_day 高质量明细数据入库
      */
-    public int[] batchInsertHighQualityListDay(List<Object[]> data) {
+    public void batchInsertHighQualityListDay(List<Object[]> data) {
         String sql = "INSERT INTO tsl_data.high_quality_list_day\n" +
                 "(month_id, day_id, contact_id, busino_area_name, busino_prov_name, sheet_no, busi_number, cust_star_name, sheet_type_name, serv_type_name, last_deal_content," +
                 " accept_time, archived_time, data_type_name, channel_name, profes_dep, big_type_name, small_type_name, is_dispatch_cloud, accept_channel_name, duty_reason_name," +
@@ -121,9 +121,32 @@ public class TslDataDao {
                 " solved_result_desc, cust_level_name, busi_type_name, urgent_level_name, important_type_name, is_upgrade, actual_total_len, nature_actual_total_len," +
                 " cust_satis_desc, auto_is_ok, auto_cust_satis_desc, nonauto_is_ok_name, nonauto_cust_satis_desc, prod_type_name, proc_name, merge_satis_desc, serv_type_name_new," +
                 " is_svip_keyman, customer_label, prov_name, area_id, area_name, city_id, city_name, grid_id, grid_name, is_distri_area, cp_satisfaction, cp_is_ok," +
-                " cp_timely_contact, cp_type, novisit_tag, serv_content, gis_area, gis_area_name, gis_city, gis_city_name, use_gis, month_date, day_date)\n" +
+                " cp_timely_contact, cp_type, novisit_tag, serv_content, gis_area, gis_area_name, gis_city, gis_city_name, use_gis, month_date, day_date)" +
                 "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," +
                 " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-        return jdbcTemplate.batchUpdate(sql, data);
+        jdbcTemplate.batchUpdate(sql, data);
+    }
+
+    /**
+     * high_quality_count_day 高质量统计数据入库
+     */
+    public void batchInsertHighQualityCountDay(List<Object[]> data) {
+        String sql = "insert into tsl_data.high_quality_count_day (month_id,day_id,acct_date,businoareaname,profes_dep,big_type_name,small_type_name,total_complaints," +
+                "hotline_complaints,other_complaint,litigation_volume,satisfaction_rate,satisfaction_count,total_evaluation,complaint_satisfied,complaint_satisfied_list," +
+                "complaint_satisfied_count,complaint_resolution,complaint_resolution_list,complaint_resolution_count,complaint_response,complaint_response_list," +
+                "complaint_response_count,complaint,fault_satisfaction_rate,fault_satisfaction_list,fault_satisfaction_count,fault_resolution_rate,fault_resolution_list," +
+                "fault_resolution_count,fault_response_rate,fault_response_list,fault_response_count)\n" +
+                " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+        jdbcTemplate.batchUpdate(sql, data);
+    }
+
+    public void batchInsertMobileComplaintDay(List<Object[]> data) {
+        String sql = "insert into tsl_data.mobile_complaint_day (month_id,day_id,acct_date,sheet_no,is_online_complete,contact_no,busi_no,serv_content,last_deal_content," +
+                "deal_depart_name,deal_opinion,serv_type,bus_type,duty_reason,accept_channel,submit_channel,compl_area_local,duty_major,product_name,sp_product_code," +
+                "pre_repair_name,pre_repair_charges,fault_location,cust_level,satisfaction_in_reply,is_ok_in_reply,accept_time,end_time,proce_time,cust_area,is_cust_serv_complete," +
+                "is_send_sheet_complete,is_repeat,is_upgrade,is_timeout,gis_city,process_nums,deal_depart_name_1,deal_depart_name_2,deal_depart_name_3,first_call_back_time," +
+                "proce_remark,duty_major_day,duty_reason_id_day,duty_major_month,duty_reason_id_month,voice_text)" +
+                " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+        jdbcTemplate.batchUpdate(sql, data);
     }
 }

+ 0 - 9
src/main/java/com/nokia/tsl_data/dao/TslMapper.java

@@ -109,15 +109,6 @@ public interface TslMapper {
     @Deprecated
     List<Map<String, Object>> selectTargetTsRatioForMonth(String monthId);
 
-    /**
-     * 插入用户数
-     */
-    void insertUserCount(@Param("map") Map<String, Object> map);
-
-    /**
-     * 插入目标万投比
-     */
-    void insertTargetTsRatio(@Param("map") Map<String, Object> map);
 
     /**
      * 删除某天的客户端数据

+ 0 - 23
src/main/java/com/nokia/tsl_data/dao/UserCountMapper.java

@@ -1,23 +0,0 @@
-package com.nokia.tsl_data.dao;
-
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Select;
-
-import java.util.List;
-import java.util.Map;
-
-@Mapper
-public interface UserCountMapper {
-
-    /**
-     * 按月查询管理端用户数
-     */
-    @Select("select city_name, management_user_count from report_auto.user_count where month_id = #{monthId}")
-    List<Map<String, Object>> selectMangementUserCountForMonth(String monthId);
-
-    /**
-     * 按月查询客户端用户数
-     */
-    @Select("select city_name, customer_user_count from report_auto.user_count where month_id = #{monthId}")
-    List<Map<String, Object>> selectCustomerUserCountForMonth(String monthId);
-}

+ 9 - 0
src/main/java/com/nokia/tsl_data/dao/UserCountRepository.java

@@ -6,9 +6,18 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface UserCountRepository extends JpaRepository<UserCount, Long> {
 
     @Query("select e from UserCount e where e.monthId = :month and e.cityName = :city")
     UserCount findByMonthAndCity(@Param("month") String month, @Param("city") String city);
+
+    /**
+     * 按月查询客户端用户数
+     */
+    @Query("select t from UserCount t where t.monthId = :monthId")
+    List<UserCount> selectUserCountForMonth(@Param("monthId") String monthId);
+
 }

+ 1 - 1
src/main/java/com/nokia/tsl_data/properties/DataWarehouseProperties.java

@@ -35,5 +35,5 @@ public class DataWarehouseProperties {
     // HighQualityCountDay 文件前缀
     private String prefixOfMobileComplaint = "HE_D_MOBILE_COMPLAINT_DETAILS_DAY_1087468015013851136_";
     // HighQualityCountDay 字段数量
-    private Integer filedNumOfMobileComplaint = 47;
+    private Integer filedNumOfMobileComplaintDay = 47;
 }

+ 10 - 7
src/main/java/com/nokia/tsl_data/service/DataWarehouseService.java

@@ -18,6 +18,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+/**
+ * 从能力商店订阅的表入库
+ */
 @Slf4j
 @Service
 public class DataWarehouseService {
@@ -124,7 +127,7 @@ public class DataWarehouseService {
     /**
      * 入库 河北高质量2日明细数据
      */
-    private void warehouseHighQualityListDay(File file) {
+    public void warehouseHighQualityListDay(File file) {
         try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
             // SOH作为分割符
             char delimiter = 1;
@@ -158,7 +161,7 @@ public class DataWarehouseService {
     /**
      * 入库 河北_CEM移网质量投诉明细
      */
-    private void warehouseMobileComplaintDay(File file) {
+    public void warehouseMobileComplaintDay(File file) {
         try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
             // SOH作为分割符
             char delimiter = 1;
@@ -171,13 +174,13 @@ public class DataWarehouseService {
             List<CSVRecord> records = parser.getRecords();
             List<Object[]> list = new ArrayList<>();
             for (CSVRecord record : records) {
-                Object[] ps = new Object[dataWarehouseProperties.getFiledNumOfMobileComplaint().intValue()];
+                Object[] ps = new Object[dataWarehouseProperties.getFiledNumOfMobileComplaintDay().intValue()];
                 list.add(ps);
                 for (int i = 0; i < ps.length; i++) {
                     ps[i] = record.get(i);
                 }
             }
-            tslDataDao.batchInsertHighQualityListDay(list);
+            tslDataDao.batchInsertMobileComplaintDay(list);
         } catch (IOException e) {
             e.printStackTrace();
             throw new RuntimeException("河北_CEM移网质量投诉明细数据入库失败..." + e.getMessage());
@@ -187,7 +190,7 @@ public class DataWarehouseService {
     /**
      * 入库 河北_CEM高品质2日统计
      */
-    private void warehouseHighQualityCountDay(File file) {
+    public void warehouseHighQualityCountDay(File file) {
         try (Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
             // SOH作为分割符
             char delimiter = 1;
@@ -200,13 +203,13 @@ public class DataWarehouseService {
             List<CSVRecord> records = parser.getRecords();
             List<Object[]> list = new ArrayList<>();
             for (CSVRecord record : records) {
-                Object[] ps = new Object[dataWarehouseProperties.getFiledNumOfMobileComplaint().intValue()];
+                Object[] ps = new Object[dataWarehouseProperties.getFiledNumOfHighQualityCountDay().intValue()];
                 list.add(ps);
                 for (int i = 0; i < ps.length; i++) {
                     ps[i] = record.get(i);
                 }
             }
-            tslDataDao.batchInsertHighQualityListDay(list);
+            tslDataDao.batchInsertHighQualityCountDay(list);
         } catch (IOException e) {
             e.printStackTrace();
             throw new RuntimeException("河北_CEM高品质2日统计数据入库失败..." + e.getMessage());

+ 26 - 30
src/main/java/com/nokia/tsl_data/service/TslDataService.java

@@ -2,8 +2,9 @@ package com.nokia.tsl_data.service;
 
 import com.nokia.tsl_data.dao.MobileComplaintMapper;
 import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
-import com.nokia.tsl_data.dao.TargetTsRatioMapper;
+import com.nokia.tsl_data.dao.TargetTsRatioRepository;
 import com.nokia.tsl_data.dao.TslMapper;
+import com.nokia.tsl_data.entity.TargetTsRatio;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -21,9 +22,9 @@ public class TslDataService {
     private final TslMapper tslMapper;
     private final MobileComplaintMapper mobileComplaintMapper;
     private final SysDataDictionaryRepository sysDataDictionaryRepository;
-    private final TargetTsRatioMapper targetTsRatioMapper;
     private final HighQualityCountService highQualityCountService;
     private final UserCountService userCountService;
+    private final TargetTsRatioRepository targetTsRatioRepository;
 
     @Value("${tslTask.compliance.satisfied:0.92}")
     private double satisfiedCompliance;
@@ -32,13 +33,13 @@ public class TslDataService {
     @Value("${tslTask.compliance.response:0.99}")
     private double responseCompliance;
 
-    public TslDataService(TslMapper tslMapper, MobileComplaintMapper mobileComplaintMapper, SysDataDictionaryRepository sysDataDictionaryRepository, TargetTsRatioMapper targetTsRatioMapper, HighQualityCountService highQualityCountService, UserCountService userCountService) {
+    public TslDataService(TslMapper tslMapper, MobileComplaintMapper mobileComplaintMapper, SysDataDictionaryRepository sysDataDictionaryRepository, HighQualityCountService highQualityCountService, UserCountService userCountService, TargetTsRatioRepository targetTsRatioRepository) {
         this.tslMapper = tslMapper;
         this.mobileComplaintMapper = mobileComplaintMapper;
         this.sysDataDictionaryRepository = sysDataDictionaryRepository;
-        this.targetTsRatioMapper = targetTsRatioMapper;
         this.highQualityCountService = highQualityCountService;
         this.userCountService = userCountService;
+        this.targetTsRatioRepository = targetTsRatioRepository;
     }
 
     /**
@@ -181,9 +182,7 @@ public class TslDataService {
             }
         }
         // 逆序排序
-        result.sort((o1, o2) -> {
-            return Double.compare((double) o2.get(3), (double) o1.get(3));
-        });
+        result.sort((o1, o2) -> Double.compare((double) o2.get(3), (double) o1.get(3)));
         // 全省数据
         List<Object> list = new ArrayList<>();
         result.add(list);
@@ -286,9 +285,7 @@ public class TslDataService {
             list.add(6, ((double) list.get(4)) - ((double) list.get(3)));
         }
         // 排序--逆序
-        result.sort((o1, o2) -> {
-            return Double.compare((double) o2.get(6), (double) o1.get(6));
-        });
+        result.sort((o1, o2) -> Double.compare((double) o2.get(6), (double) o1.get(6)));
         // 全省数据
         List<Object> list = new ArrayList<>(7);
         result.add(list);
@@ -317,16 +314,16 @@ public class TslDataService {
         for (String area : sysDataDictionaryRepository.findAllCityName()) {
             List<Object> list = new ArrayList<>();
             int[] js = complaintsForDay.get(area);
-            for (int i = 0; i < js.length; i++) {
-                list.add(js[i]);
+            for (int j : js) {
+                list.add(j);
             }
             result.put(area, list);
         }
         // 写入全省数据
         result.put("全省", new ArrayList<>());
         int[] js = complaintsForDay.get("全省");
-        for (int i = 0; i < js.length; i++) {
-            result.get("全省").add(js[i]);
+        for (int j : js) {
+            result.get("全省").add(j);
         }
         // 客户端用户数
         Map<String, Double> customerUserCount = userCountService.getCustomerUserCountForMonth(day.substring(0, 6));
@@ -358,10 +355,9 @@ public class TslDataService {
 
         // 期望万投率--从数据库取出来是一个字符串
         // 客户端目标投诉率
-        List<Map<String, Object>> targetTsRatio = targetTsRatioMapper
-                .selectCustomerTargetTsRatioForMonth(day.substring(0, 6));
-        for (Map<String, Object> map : targetTsRatio) {
-            result.get(map.get("city_name")).add(Double.parseDouble(map.get("customer_target_ts_ratio").toString()));
+        List<TargetTsRatio> targetTsRatios = targetTsRatioRepository.findByMonthId(day.substring(0, 6));
+        for (TargetTsRatio targetTsRatio : targetTsRatios) {
+            result.get(targetTsRatio.getCityName()).add(targetTsRatio.getCustomerTargetRatio());
         }
 
         // 与目标差距
@@ -390,10 +386,10 @@ public class TslDataService {
         int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
         // monthId
         String monthId = new SimpleDateFormat("yyyyMM").format(calendar.getTime());
-
-        List<Map<String, Object>> cityTslforMonth = mobileComplaintMapper.selectCityTslForMonth(day);
-        List<Map<String, Object>> allTslforMonth = mobileComplaintMapper.selectAllTslForMonth(day);
-        List<Map<String, Object>> cityAllforMonth = mobileComplaintMapper.selectCityAllForMonth(day);
+        // 读取数据库数据
+        List<Map<String, Object>> cityTslForMonth = mobileComplaintMapper.selectCityTslForMonth(day);
+        List<Map<String, Object>> allTslForMonth = mobileComplaintMapper.selectAllTslForMonth(day);
+        List<Map<String, Object>> cityAllForMonth = mobileComplaintMapper.selectCityAllForMonth(day);
         int total = mobileComplaintMapper.selectAllForMonth(day);
 
         int dayIndex = Integer.parseInt(day.substring(6, 8));
@@ -409,17 +405,17 @@ public class TslDataService {
         result.put("全省", new ArrayList<>());
 
         // 各地市每日投诉量
-        for (Map<String, Object> map : cityTslforMonth) {
+        for (Map<String, Object> map : cityTslForMonth) {
             int dayId = Integer.parseInt(map.get("day_id").toString());
-            result.get(map.get("compl_area_local")).set(dayId - 1, map.get("num"));
+            result.get(map.get("compl_area_local").toString()).set(dayId - 1, map.get("num"));
         }
         // 全省每日投诉量
-        for (Map<String, Object> map : allTslforMonth) {
+        for (Map<String, Object> map : allTslForMonth) {
             result.get("全省").add(map.get("num"));
         }
         // 各地市投诉总量
-        for (Map<String, Object> map : cityAllforMonth) {
-            result.get(map.get("compl_area_local")).add(map.get("num"));
+        for (Map<String, Object> map : cityAllForMonth) {
+            result.get(map.get("compl_area_local").toString()).add(map.get("num"));
         }
         // 全省总量
         result.get("全省").add(total);
@@ -442,9 +438,9 @@ public class TslDataService {
         }
         // 期望万投率--从数据库取出来是一个字符串
         // 服务端目标投诉率
-        List<Map<String, Object>> targetTsRatio = targetTsRatioMapper.selectManagementTargetTsRatioForMonth(monthId);
-        for (Map<String, Object> map : targetTsRatio) {
-            result.get(map.get("city_name")).add(Double.parseDouble(map.get("management_target_ts_ratio").toString()));
+        List<TargetTsRatio> targetTsRatios = targetTsRatioRepository.findByMonthId(monthId);
+        for (TargetTsRatio targetTsRatio : targetTsRatios) {
+            result.get(targetTsRatio.getCityName()).add(targetTsRatio.getManagementTargetRatio());
         }
         // 与目标差距
         for (Entry<String, List<Object>> entry : result.entrySet()) {

+ 1001 - 0
src/main/java/com/nokia/tsl_data/service/TslReportService.java

@@ -0,0 +1,1001 @@
+package com.nokia.tsl_data.service;
+
+import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.RegionUtil;
+import org.apache.poi.xssf.usermodel.*;
+import org.springframework.stereotype.Service;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * 投诉报表数据生成
+ */
+@Slf4j
+@Service
+public class TslReportService {
+
+    private final TslDataService tslDataService;
+    private final SysDataDictionaryRepository sysDataDictionaryRepository;
+
+    private XSSFWorkbook workbook = null;
+
+    private static final DateFormat DAY_FORMAT = new SimpleDateFormat("yyyyMMdd");
+
+    public TslReportService(TslDataService tslDataService, SysDataDictionaryRepository sysDataDictionaryRepository) {
+        this.tslDataService = tslDataService;
+        this.sysDataDictionaryRepository = sysDataDictionaryRepository;
+    }
+
+    /**
+     * 写入workbook
+     */
+    public void workbookToFile(String day, String path) {
+        // 每次需要重置workbook
+        workbook = new XSSFWorkbook();
+        // 按照顺序写入各个sheet
+        // 管理端-移网质量类
+        getSheet1(day);
+        // 客户端-战略考核
+        getSheet1_1(day);
+        // 管理端-重复投诉率
+        getSheet2(day);
+        // 投诉处理时长、超时工单概况
+        getSheet3(day);
+        // 客户端-投诉问题解决满意度 客户端-投诉问题解决率 客户端-投诉问题响应率
+        getSheet4_6(day);
+        try (OutputStream outputStream = new FileOutputStream(path)) {
+            workbook.write(outputStream);
+            workbook.close();
+            workbook = null;
+        } catch (Exception e) {
+            log.error("写入失败。。。" + e.getMessage());
+        }
+    }
+
+    /**
+     * 客户端-投诉问题解决满意度
+     * 客户端-投诉问题解决率
+     * 客户端-投诉问题响应率
+     */
+    private void getSheet4_6(String day) {
+        // 计算时间常数
+        Calendar calendar = Calendar.getInstance(Locale.CHINA);
+        try {
+            calendar.setTime(DAY_FORMAT.parse(day));
+        } catch (ParseException e) {
+            log.error("时间字符串解析失败--{}", day);
+        }
+        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
+        Sheet sheet4 = getWorkbook().createSheet("客户端-投诉问题解决满意度");
+        Sheet sheet5 = getWorkbook().createSheet("客户端-投诉问题解决率");
+        Sheet sheet6 = getWorkbook().createSheet("客户端-投诉问题响应率");
+        Row row;
+        Cell cell;
+        CellRangeAddress rangeAddress;
+        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
+        XSSFFont font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setFontHeightInPoints((short) 10);
+        // 基本模式 微软雅黑 10号字 带全边框 水平居中
+        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
+        baseStyle.setFont(font);
+        baseStyle.setAlignment(HorizontalAlignment.CENTER);
+        baseStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        baseStyle.setBorderBottom(BorderStyle.THIN);
+        baseStyle.setBorderTop(BorderStyle.THIN);
+        baseStyle.setBorderLeft(BorderStyle.THIN);
+        baseStyle.setBorderRight(BorderStyle.THIN);
+        // 样式1 与base相同
+        XSSFCellStyle cellStyle1 = baseStyle.copy();
+        // 样式2 百分比 2位小数
+        XSSFCellStyle cellStyle2 = baseStyle.copy();
+        cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
+        // 样式3 自动换行 背景色FFE7E6E6 FFAEAAAA
+        XSSFCellStyle cellStyle3 = baseStyle.copy();
+        // cellStyle3.setWrapText(true);
+        XSSFColor color = new XSSFColor();
+        color.setARGBHex("FFAEAAAA");
+        cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        cellStyle3.setFillForegroundColor(color);
+
+        List<List<List<Object>>> sheet4_6Data = tslDataService.getSheet4_6Data(day);
+
+        // 客户端-投诉问题解决满意度 第一行
+        row = sheet4.createRow(0);
+        cell = row.createCell(0);
+        cell.setCellValue(String.format("投诉问题解决满意率(1-%s)", dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 A1 - D1
+        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
+        addMergedRegion(sheet4, rangeAddress);
+        // 客户端-投诉问题解决满意度 第二行
+        row = sheet4.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(1);
+        cell.setCellValue("满意率");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(2);
+        cell.setCellValue("达标值");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(3);
+        cell.setCellValue("与达标值差距");
+        cell.setCellStyle(cellStyle3);
+        int rowNum = 2;
+        for (List<Object> list : sheet4_6Data.get(0)) {
+            row = sheet4.createRow(rowNum++);
+            // 地市
+            cell = row.createCell(0);
+            cell.setCellValue(list.get(0).toString());
+            cell.setCellStyle(cellStyle1);
+            // 投诉问题解决满意率
+            cell = row.createCell(1);
+            cell.setCellValue(((double) list.get(1)));
+            cell.setCellStyle(cellStyle2);
+            // 达标值
+            cell = row.createCell(2);
+            cell.setCellValue((double) list.get(2));
+            cell.setCellStyle(cellStyle2);
+            // 与达标值差距
+            cell = row.createCell(3);
+            cell.setCellValue(((double) list.get(3)));
+            cell.setCellStyle(cellStyle2);
+        }
+        // 设置条件格式D3-D14
+        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
+        setConditionalFormatting2(sheet4, rangeAddress);
+
+        // 设置列宽 2048 1304 2048 2304
+        for (int i = 0; i < 4; i++) {
+            sheet4.setColumnWidth(i, 2848);
+        }
+
+        // 设置行高 15.0 15.0...
+        for (int i = 0; i < 15; i++) {
+            sheet4.getRow(i).setHeightInPoints(15.0F);
+        }
+
+        // 客户端-投诉问题解决率
+        row = sheet5.createRow(0);
+        cell = row.createCell(0);
+        cell.setCellValue(String.format("投诉问题解决率(1-%s)", dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 A1 - D1
+        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
+        addMergedRegion(sheet5, rangeAddress);
+        // 客户端-投诉问题解决率 第二行
+        row = sheet5.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(1);
+        cell.setCellValue("解决率");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(2);
+        cell.setCellValue("达标值");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(3);
+        cell.setCellValue("与达标值差距");
+        cell.setCellStyle(cellStyle3);
+        rowNum = 2;
+        for (List<Object> list : sheet4_6Data.get(1)) {
+            row = sheet5.createRow(rowNum++);
+            // 地市
+            cell = row.createCell(0);
+            cell.setCellValue(list.get(0).toString());
+            cell.setCellStyle(cellStyle1);
+            // 投诉问题解决率
+            cell = row.createCell(1);
+            cell.setCellValue(((double) list.get(1)));
+            cell.setCellStyle(cellStyle2);
+            // 达标值
+            cell = row.createCell(2);
+            cell.setCellValue((double) list.get(2));
+            cell.setCellStyle(cellStyle2);
+            // 与达标值差距
+            cell = row.createCell(3);
+            cell.setCellValue(((double) list.get(3)));
+            cell.setCellStyle(cellStyle2);
+        }
+        // 设置条件格式D3-D14
+        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
+        setConditionalFormatting2(sheet5, rangeAddress);
+
+        // 设置列宽 2048 1304 2048 2304
+        for (int i = 0; i < 4; i++) {
+            sheet5.setColumnWidth(i, 2848);
+        }
+
+        // 设置行高 15.0 15.0...
+        for (int i = 0; i < 15; i++) {
+            sheet5.getRow(i).setHeightInPoints(15.0F);
+        }
+
+        // 客户端-投诉问题响应率
+        row = sheet6.createRow(0);
+        cell = row.createCell(0);
+        cell.setCellValue(String.format("投诉问题响应率(1-%s)", dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 A1 - D1
+        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
+        addMergedRegion(sheet6, rangeAddress);
+        // 客户端-投诉问题响应率 第二行
+        row = sheet6.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(1);
+        cell.setCellValue("响应率");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(2);
+        cell.setCellValue("达标值");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(3);
+        cell.setCellValue("与达标值差距");
+        cell.setCellStyle(cellStyle3);
+        rowNum = 2;
+        for (List<Object> list : sheet4_6Data.get(2)) {
+            row = sheet6.createRow(rowNum++);
+            // 地市
+            cell = row.createCell(0);
+            cell.setCellValue(list.get(0).toString());
+            cell.setCellStyle(cellStyle1);
+            // 投诉问题解决率
+            cell = row.createCell(1);
+            cell.setCellValue(((double) list.get(1)));
+            cell.setCellStyle(cellStyle2);
+            // 达标值
+            cell = row.createCell(2);
+            cell.setCellValue((double) list.get(2));
+            cell.setCellStyle(cellStyle2);
+            // 与达标值差距
+            cell = row.createCell(3);
+            cell.setCellValue(((double) list.get(3)));
+            cell.setCellStyle(cellStyle2);
+        }
+        // 设置条件格式D3-D14
+        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
+        setConditionalFormatting2(sheet6, rangeAddress);
+
+        // 设置列宽 2048 1304 2048 2304
+        for (int i = 0; i < 4; i++) {
+            sheet6.setColumnWidth(i, 2848);
+        }
+
+        // 设置行高 15.0 15.0...
+        for (int i = 0; i < 15; i++) {
+            sheet6.getRow(i).setHeightInPoints(15.0F);
+        }
+    }
+
+    /**
+     * 投诉处理时长、超时工单概况
+     */
+    private void getSheet3(String day) {
+        // 计算时间常数
+        Calendar calendar = Calendar.getInstance(Locale.CHINA);
+        try {
+            calendar.setTime(DAY_FORMAT.parse(day));
+        } catch (ParseException e) {
+            log.error("时间字符串解析失败--{}", day);
+        }
+        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
+        // 修正,MONTH是从0开始
+        int monthOfYear = calendar.get(Calendar.MONTH) + 1;
+        int preMonthOfYear = monthOfYear > 1 ? monthOfYear - 1 : 12;
+
+        Sheet sheet = getWorkbook().createSheet("投诉处理时长、超时工单概况");
+        Row row;
+        Cell cell;
+        CellRangeAddress rangeAddress;
+        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
+        XSSFFont font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setFontHeightInPoints((short) 10);
+        // 基本模式 微软雅黑 10号字 带全边框 水平居中
+        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
+        baseStyle.setFont(font);
+        baseStyle.setAlignment(HorizontalAlignment.CENTER);
+        baseStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        baseStyle.setBorderBottom(BorderStyle.THIN);
+        baseStyle.setBorderTop(BorderStyle.THIN);
+        baseStyle.setBorderLeft(BorderStyle.THIN);
+        baseStyle.setBorderRight(BorderStyle.THIN);
+        // 样式1 与base相同
+        XSSFCellStyle cellStyle1 = baseStyle.copy();
+        // 样式2 百分比 2位小数
+        XSSFCellStyle cellStyle2 = baseStyle.copy();
+        cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
+        // 样式3 自动换行 背景色FFE7E6E6 FFAEAAAA
+        XSSFCellStyle cellStyle3 = baseStyle.copy();
+        // cellStyle3.setWrapText(true);
+        XSSFColor color = new XSSFColor();
+        color.setARGBHex("FFAEAAAA");
+        cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        cellStyle3.setFillForegroundColor(color);
+        // 样式4 小数 保留2位
+        XSSFCellStyle cellStyle4 = baseStyle.copy();
+        cellStyle4.setDataFormat(dataFormat.getFormat("0.00"));
+
+        // 第一行
+        row = sheet.createRow(0);
+        cell = row.createCell(0);
+        cell.setCellValue(String.format("超时工单情况(1-%s)", dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 A1 - D1
+        rangeAddress = new CellRangeAddress(0, 0, 0, 3);
+        addMergedRegion(sheet, rangeAddress);
+        cell = row.createCell(6);
+        cell.setCellValue(String.format("平均处理时长(1-%s)", dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 G1 - J1
+        rangeAddress = new CellRangeAddress(0, 0, 6, 9);
+        addMergedRegion(sheet, rangeAddress);
+
+        // 第二行
+        row = sheet.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(1);
+        cell.setCellValue("工单数");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(2);
+        cell.setCellValue("超时工单数");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(3);
+        cell.setCellValue("超时工单占比");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(6);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(7);
+        cell.setCellValue(String.format("%s月", preMonthOfYear));
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(8);
+        cell.setCellValue(String.format("%s月", monthOfYear));
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(9);
+        cell.setCellValue("涨幅");
+        cell.setCellStyle(cellStyle3);
+
+        // 写入超时工单情况
+        List<List<Object>> sheet3Data1 = tslDataService.getSheet3Data1(day);
+        int rowNum = 2;
+        for (List<Object> list : sheet3Data1) {
+            row = sheet.createRow(rowNum++);
+            // 地市
+            cell = row.createCell(0);
+            cell.setCellValue(list.get(0).toString());
+            cell.setCellStyle(cellStyle1);
+            // 工单数
+            cell = row.createCell(1);
+            cell.setCellValue((long) list.get(1));
+            cell.setCellStyle(cellStyle1);
+            // 超时工单数
+            cell = row.createCell(2);
+            cell.setCellValue((long) list.get(2));
+            cell.setCellStyle(cellStyle1);
+            // 超时工单占比
+            cell = row.createCell(3);
+            cell.setCellValue(((double) list.get(3)));
+            cell.setCellStyle(cellStyle2);
+        }
+        // 设置条件格式D3-D14
+        rangeAddress = new CellRangeAddress(2, 13, 3, 3);
+        setConditionalFormatting(sheet, rangeAddress);
+
+        // 写入平均处理时长
+        List<List<Object>> sheet3Data2 = tslDataService.getSheet3Data2(day);
+        rowNum = 2;
+        for (List<Object> list : sheet3Data2) {
+            row = sheet.getRow(rowNum++);
+            // 地市
+            cell = row.createCell(6);
+            cell.setCellValue(list.get(0).toString());
+            cell.setCellStyle(cellStyle1);
+            // 上月
+            cell = row.createCell(7);
+            cell.setCellValue((double) list.get(1));
+            cell.setCellStyle(cellStyle4);
+            // 当月
+            cell = row.createCell(8);
+            cell.setCellValue((double) list.get(2));
+            cell.setCellStyle(cellStyle4);
+            // 涨幅
+            cell = row.createCell(9);
+            cell.setCellValue((double) list.get(3));
+            cell.setCellStyle(cellStyle4);
+        }
+        // 设置条件格式J3-J14
+        rangeAddress = new CellRangeAddress(2, 13, 9, 9);
+        setConditionalFormatting(sheet, rangeAddress);
+
+        // 设置列宽 2048 2276*3 2048*3 2276*2 3612
+        for (int i = 0; i < 10; i++) {
+            sheet.setColumnWidth(i, 2848);
+        }
+
+        // 设置行高 14.25 25.5 14.25...
+        for (int i = 0; i < 15; i++) {
+            sheet.getRow(i).setHeightInPoints(15.0F);
+        }
+    }
+
+    /**
+     * 管理端-重复投诉率
+     */
+    private void getSheet2(String day) {
+        // 计算时间常数
+        Calendar calendar = Calendar.getInstance(Locale.CHINA);
+        try {
+            calendar.setTime(DAY_FORMAT.parse(day));
+        } catch (ParseException e) {
+            log.error("时间字符串解析失败--{}", day);
+        }
+        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
+        int monthOfYear = calendar.get(Calendar.MONTH) + 1;
+        // 显示当前和前一天的对比
+        int preDayOfMonth = (dayOfMonth > 1) ? dayOfMonth - 1 : dayOfMonth;
+
+        Sheet sheet = getWorkbook().createSheet("管理端-重复投诉率");
+        Row row;
+        Cell cell;
+        CellRangeAddress rangeAddress;
+        XSSFFont font;
+        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
+        // 基本模式 微软雅黑 10号字 带全边框 水平居中
+        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
+        font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setFontHeightInPoints((short) 10);
+        baseStyle.setFont(font);
+        baseStyle.setAlignment(HorizontalAlignment.CENTER);
+        baseStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        baseStyle.setBorderBottom(BorderStyle.THIN);
+        baseStyle.setBorderTop(BorderStyle.THIN);
+        baseStyle.setBorderLeft(BorderStyle.THIN);
+        baseStyle.setBorderRight(BorderStyle.THIN);
+        // 基础模式
+        XSSFCellStyle cellStyle1 = baseStyle.copy();
+        // 带边框 百分比 2位小数
+        XSSFCellStyle cellStyle2 = baseStyle.copy();
+        cellStyle2.setDataFormat(dataFormat.getFormat("0.00%"));
+        // 微软雅黑 10号字 自动换行 背景色FFE7E6E6 FFAEAAAA
+        XSSFCellStyle cellStyle3 = baseStyle.copy();
+        // cellStyle3.setWrapText(true);
+        XSSFColor color = new XSSFColor();
+        color.setARGBHex("FFAEAAAA");
+        cellStyle3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        cellStyle3.setFillForegroundColor(color);
+
+        // 第一行 标题栏
+        row = sheet.createRow(0);
+        cell = row.createCell(0);
+        cell.setCellValue(String.format("重复投诉率(1-%s)", dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 A1 - G1
+        rangeAddress = new CellRangeAddress(0, 0, 0, 6);
+        addMergedRegion(sheet, rangeAddress);
+
+        // 第二行
+        row = sheet.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(1);
+        cell.setCellValue("工单数");
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 B2-C2
+        rangeAddress = new CellRangeAddress(1, 1, 1, 2);
+        addMergedRegion(sheet, rangeAddress);
+        cell = row.createCell(3);
+        cell.setCellValue("重复投诉率");
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 B2-C2
+        rangeAddress = new CellRangeAddress(1, 1, 3, 4);
+        addMergedRegion(sheet, rangeAddress);
+        cell = row.createCell(5);
+        cell.setCellValue("增量");
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格 F2-G2
+        rangeAddress = new CellRangeAddress(1, 1, 5, 6);
+        addMergedRegion(sheet, rangeAddress);
+
+        // 第三行
+        row = sheet.createRow(2);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(1);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(2);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(3);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(4);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(5);
+        cell.setCellValue("工单数");
+        cell.setCellStyle(cellStyle3);
+        cell = row.createCell(6);
+        cell.setCellValue("重复投诉率");
+        cell.setCellStyle(cellStyle3);
+
+        // 写入数据行
+        List<List<Object>> sheet2Data = tslDataService.getSheet2Data(day);
+        int rowNum = 3;
+        for (List<Object> list : sheet2Data) {
+            row = sheet.createRow(rowNum++);
+            cell = row.createCell(0);
+            // 地市
+            cell.setCellValue(list.get(0).toString());
+            cell.setCellStyle(cellStyle1);
+            // 前一天重复工单数
+            cell = row.createCell(1);
+            cell.setCellValue(((double) list.get(1)));
+            cell.setCellStyle(cellStyle1);
+            // 当天重复工单数
+            cell = row.createCell(2);
+            cell.setCellValue(((double) list.get(2)));
+            cell.setCellStyle(cellStyle1);
+            // 前一天重复投诉率
+            cell = row.createCell(3);
+            cell.setCellValue(((double) list.get(3)));
+            cell.setCellStyle(cellStyle2);
+            // 当前重复投诉率
+            cell = row.createCell(4);
+            cell.setCellValue(((double) list.get(4)));
+            cell.setCellStyle(cellStyle2);
+            // 重复工单增量
+            cell = row.createCell(5);
+            cell.setCellValue(((double) list.get(5)));
+            cell.setCellStyle(cellStyle1);
+            // 重复投诉率增量
+            cell = row.createCell(6);
+            cell.setCellValue(((double) list.get(6)));
+            cell.setCellStyle(cellStyle2);
+        }
+
+        // 添加条件格式F4-F15
+        rangeAddress = new CellRangeAddress(3, 14, 5, 5);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式G4-G15
+        rangeAddress = new CellRangeAddress(3, 14, 6, 6);
+        setConditionalFormatting(sheet, rangeAddress);
+
+        // 设置列宽2048
+        for (int i = 0; i <= 6; i++) {
+            sheet.setColumnWidth(i, 2848);
+        }
+
+        // 设置行高 15.0 ...
+        for (int i = 0; i < 16; i++) {
+            sheet.getRow(i).setHeightInPoints(15.0F);
+        }
+    }
+
+    /**
+     * 20230627新增 客户端-战略考核
+     */
+    private void getSheet1_1(String day) {
+        Sheet sheet = getWorkbook().createSheet("客户端-战略考核");
+
+        // 计算天数
+        LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern("yyyyMMdd"));
+        int dayOfMonth = date.getDayOfMonth();
+
+        Row row;
+        Cell cell;
+        CellRangeAddress rangeAddress;
+        XSSFFont font;
+        XSSFDataFormat dataFormat = getWorkbook().createDataFormat();
+
+        // 基本模式 微软雅黑 10号字 带全边框 水平居中
+        XSSFCellStyle baseStyle = getWorkbook().createCellStyle();
+        font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setFontHeightInPoints((short) 10);
+        baseStyle.setFont(font);
+        baseStyle.setAlignment(HorizontalAlignment.CENTER);
+        baseStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        baseStyle.setBorderBottom(BorderStyle.THIN);
+        baseStyle.setBorderTop(BorderStyle.THIN);
+        baseStyle.setBorderLeft(BorderStyle.THIN);
+        baseStyle.setBorderRight(BorderStyle.THIN);
+        // 基础模式
+        XSSFCellStyle cellStyle1 = baseStyle.copy();
+        // 2位小数
+        XSSFCellStyle cellStyle2 = baseStyle.copy();
+        cellStyle2.setDataFormat(dataFormat.getFormat("0.00"));
+        // 微软雅黑 10号 加粗
+        XSSFCellStyle cellStyle3 = baseStyle.copy();
+        font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setBold(true);
+        font.setFontHeightInPoints((short) 10);
+        cellStyle3.setFont(font);
+
+        // 第一行 标题栏2023年客服投诉清单各地市投诉率情况(客户端-战略考核)
+        cell = sheet.createRow(0).createCell(0);
+        cell.setCellValue(day.substring(0, 4) + "年客服投诉清单各地市投诉率情况(客户端-战略考核)");
+        cell.setCellStyle(cellStyle3);
+        // 合并单元格
+        rangeAddress = new CellRangeAddress(0, 0, 0, dayOfMonth + 7);
+        sheet.addMergedRegion(rangeAddress);
+        // 设置合并单元格的边框
+        RegionUtil.setBorderBottom(BorderStyle.THIN, rangeAddress, sheet);
+        RegionUtil.setBorderTop(BorderStyle.THIN, rangeAddress, sheet);
+        RegionUtil.setBorderLeft(BorderStyle.THIN, rangeAddress, sheet);
+        RegionUtil.setBorderRight(BorderStyle.THIN, rangeAddress, sheet);
+
+        // 第二行 列名
+        row = sheet.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle1);
+        for (int i = 1; i <= dayOfMonth; i++) {
+            cell = row.createCell(i);
+            cell.setCellValue(i + "日");
+            cell.setCellStyle(cellStyle1);
+        }
+        cell = row.createCell(dayOfMonth + 1);
+        cell.setCellValue("投诉总量");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 2);
+        cell.setCellValue("用户数");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 3);
+        cell.setCellValue("目前万投率");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 4);
+        cell.setCellValue("本月预测");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 5);
+        cell.setCellValue("目标值");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 6);
+        cell.setCellValue("与目标差距");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 7);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle1);
+
+        // 获取数据
+        Map<String, List<Object>> seet1_1Data = tslDataService.getSheet1_1Data(day);
+
+        int rowNum = 2;
+        int cellNum = 0;
+        // 写入各地市数据
+        for (String area : sysDataDictionaryRepository.findAllCityName()) {
+            row = sheet.createRow(rowNum++);
+            // 写入A列的地市
+            cell = row.createCell(cellNum++);
+            cell.setCellValue(area);
+            cell.setCellStyle(cellStyle1);
+            for (Object obj : seet1_1Data.get(area)) {
+                cell = row.createCell(cellNum++);
+                cell.setCellValue(Double.parseDouble(obj.toString()));
+                cell.setCellStyle(cellStyle1);
+            }
+            // 写入最后一列的地市
+            cell = row.createCell(cellNum);
+            cell.setCellValue(area);
+            cell.setCellStyle(cellStyle1);
+            // cellNum复位
+            cellNum = 0;
+        }
+        // 写入全省数据
+        row = sheet.createRow(rowNum);
+        // 写入A列的地市
+        cell = row.createCell(cellNum++);
+        cell.setCellValue("全省");
+        cell.setCellStyle(cellStyle1);
+        for (Object obj : seet1_1Data.get("全省")) {
+            cell = row.createCell(cellNum++);
+            cell.setCellValue(Double.parseDouble(obj.toString()));
+            cell.setCellStyle(cellStyle1);
+        }
+        // 写入最后一列的地市
+        cell = row.createCell(cellNum);
+        cell.setCellValue("全省");
+        cell.setCellStyle(cellStyle1);
+
+        // 3-15行(2-14)dayOfMonth+2 - dayofMonth+6是浮点数,设置为显示小数点后2位
+        for (int i = 2; i <= 14; i++) {
+            row = sheet.getRow(i);
+            for (int j = dayOfMonth + 2; j <= dayOfMonth + 6; j++) {
+                cell = row.getCell(j);
+                cell.setCellStyle(cellStyle2);
+            }
+        }
+
+        // 添加条件格式B15-V15
+        rangeAddress = new CellRangeAddress(rowNum, rowNum, 1, dayOfMonth);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式(dayOfMonth+3)(3-14)
+        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 3, dayOfMonth + 3);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式Z3-Z14
+        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 4, dayOfMonth + 4);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式AB3-AB14
+        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 6, dayOfMonth + 6);
+        setConditionalFormatting(sheet, rangeAddress);
+
+        // 设置sheet的列宽
+        sheet.setColumnWidth(0, 1600);
+        for (int i = 1; i <= dayOfMonth; i++) {
+            sheet.setColumnWidth(i, 1100);
+        }
+        sheet.setColumnWidth(dayOfMonth + 1, 1700);
+        sheet.setColumnWidth(dayOfMonth + 2, 2100);
+        sheet.setColumnWidth(dayOfMonth + 3, 2100);
+        sheet.setColumnWidth(dayOfMonth + 4, 2100);
+        sheet.setColumnWidth(dayOfMonth + 5, 1700);
+        sheet.setColumnWidth(dayOfMonth + 6, 2100);
+        sheet.setColumnWidth(dayOfMonth + 7, 1600);
+
+        // 设置行高 15
+        for (int i = 0; i < rowNum; i++) {
+            sheet.getRow(i).setHeightInPoints(15F);
+        }
+    }
+
+    /**
+     * 管理端-移网质量类
+     */
+    private void getSheet1(String day) {
+        Sheet sheet = getWorkbook().createSheet("管理端-移网质量类");
+
+        // 计算天数
+        LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern("yyyyMMdd"));
+        int dayOfMonth = date.getDayOfMonth();
+
+        Row row;
+        Cell cell;
+
+        XSSFCellStyle cellStyle1 = getWorkbook().createCellStyle();
+        cellStyle1.setAlignment(HorizontalAlignment.CENTER);
+        cellStyle1.setVerticalAlignment(VerticalAlignment.CENTER);
+        XSSFFont font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setBold(false);
+        font.setFontHeightInPoints((short) 10);
+        cellStyle1.setFont(font);
+        cellStyle1.setBorderBottom(BorderStyle.THIN);
+        cellStyle1.setBorderTop(BorderStyle.THIN);
+        cellStyle1.setBorderLeft(BorderStyle.THIN);
+        cellStyle1.setBorderRight(BorderStyle.THIN);
+        XSSFCellStyle cellStyle3 = getWorkbook().createCellStyle();
+        cellStyle3.setAlignment(HorizontalAlignment.CENTER);
+        cellStyle3.setVerticalAlignment(VerticalAlignment.CENTER);
+        cellStyle3.setFont(font);
+        cellStyle3.setBorderBottom(BorderStyle.THIN);
+        cellStyle3.setBorderTop(BorderStyle.THIN);
+        cellStyle3.setBorderLeft(BorderStyle.THIN);
+        cellStyle3.setBorderRight(BorderStyle.THIN);
+        XSSFDataFormat format = getWorkbook().createDataFormat();
+        cellStyle3.setDataFormat(format.getFormat("0.00"));
+        XSSFCellStyle cellStyle2 = getWorkbook().createCellStyle();
+        cellStyle2.setAlignment(HorizontalAlignment.CENTER);
+        cellStyle2.setVerticalAlignment(VerticalAlignment.CENTER);
+        font = getWorkbook().createFont();
+        font.setFontName("微软雅黑");
+        font.setBold(true);
+        font.setFontHeightInPoints((short) 10);
+        cellStyle2.setFont(font);
+        cellStyle2.setBorderBottom(BorderStyle.THIN);
+        cellStyle2.setBorderTop(BorderStyle.THIN);
+        cellStyle2.setBorderLeft(BorderStyle.THIN);
+        cellStyle2.setBorderRight(BorderStyle.THIN);
+
+        // 第一行 标题栏
+        cell = sheet.createRow(0).createCell(0);
+        cell.setCellValue(day.substring(0, 4) + "年客服投诉清单各地市投诉率情况(管理端-移网质量类)");
+        cell.setCellStyle(cellStyle2);
+        // 合并单元格
+        CellRangeAddress range = new CellRangeAddress(0, 0, 0, dayOfMonth + 7);
+        sheet.addMergedRegion(range);
+        // 设置合并单元格的边框
+        RegionUtil.setBorderBottom(BorderStyle.THIN, range, sheet);
+        RegionUtil.setBorderTop(BorderStyle.THIN, range, sheet);
+        RegionUtil.setBorderLeft(BorderStyle.THIN, range, sheet);
+        RegionUtil.setBorderRight(BorderStyle.THIN, range, sheet);
+
+        // 第二行 列名
+        row = sheet.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle1);
+        for (int i = 1; i <= dayOfMonth; i++) {
+            cell = row.createCell(i);
+            cell.setCellValue(i + "日");
+            cell.setCellStyle(cellStyle1);
+        }
+        cell = row.createCell(dayOfMonth + 1);
+        cell.setCellValue("投诉总量");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 2);
+        cell.setCellValue("用户数");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 3);
+        cell.setCellValue("目前万投率");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 4);
+        cell.setCellValue("本月预测");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 5);
+        cell.setCellValue("目标值");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 6);
+        cell.setCellValue("与目标差距");
+        cell.setCellStyle(cellStyle1);
+        cell = row.createCell(dayOfMonth + 7);
+        cell.setCellValue("地市");
+        cell.setCellStyle(cellStyle1);
+
+        // 获取数据
+        Map<String, List<Object>> seet1Data = tslDataService.getSheet1Data(day);
+
+        int rowNum = 2;
+        int cellNum = 0;
+        // 写入各地市数据
+        for (String area : sysDataDictionaryRepository.findAllCityName()) {
+            row = sheet.createRow(rowNum++);
+            // 写入A列的地市
+            cell = row.createCell(cellNum++);
+            cell.setCellValue(area);
+            cell.setCellStyle(cellStyle1);
+            for (Object obj : seet1Data.get(area)) {
+                cell = row.createCell(cellNum++);
+                cell.setCellValue(Double.parseDouble(obj.toString()));
+                cell.setCellStyle(cellStyle1);
+            }
+            // 写入最后一列的地市
+            cell = row.createCell(cellNum);
+            cell.setCellValue(area);
+            cell.setCellStyle(cellStyle1);
+            // cellNum复位
+            cellNum = 0;
+        }
+        // 写入全省数据
+        row = sheet.createRow(rowNum);
+        // 写入A列的地市
+        cell = row.createCell(cellNum++);
+        cell.setCellValue("全省");
+        cell.setCellStyle(cellStyle1);
+        for (Object obj : seet1Data.get("全省")) {
+            cell = row.createCell(cellNum++);
+            cell.setCellValue(Double.parseDouble(obj.toString()));
+            cell.setCellStyle(cellStyle1);
+        }
+        // 写入最后一列的地市
+        cell = row.createCell(cellNum);
+        cell.setCellValue("全省");
+        cell.setCellStyle(cellStyle1);
+
+        // 3-15行(2-14)dayOfMonth+2 - dayOfMonth+6是浮点数,设置为显示小数点后2位
+        for (int i = 2; i <= 14; i++) {
+            row = sheet.getRow(i);
+            for (int j = dayOfMonth + 2; j <= dayOfMonth + 6; j++) {
+                cell = row.getCell(j);
+                cell.setCellStyle(cellStyle3);
+            }
+        }
+
+        // 添加条件格式B15-V15
+        CellRangeAddress rangeAddress = new CellRangeAddress(rowNum, rowNum, 1, dayOfMonth);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式(dayOfMonth+3)(3-14)
+        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 3, dayOfMonth + 3);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式Z3-Z14
+        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 4, dayOfMonth + 4);
+        setConditionalFormatting(sheet, rangeAddress);
+        // 添加条件格式AB3-AB14
+        rangeAddress = new CellRangeAddress(2, 13, dayOfMonth + 6, dayOfMonth + 6);
+        setConditionalFormatting(sheet, rangeAddress);
+
+        // 设置sheet的列宽
+        sheet.setColumnWidth(0, 1600);
+        for (int i = 1; i <= dayOfMonth; i++) {
+            sheet.setColumnWidth(i, 1100);
+        }
+        sheet.setColumnWidth(dayOfMonth + 1, 1700);
+        sheet.setColumnWidth(dayOfMonth + 2, 2100);
+        sheet.setColumnWidth(dayOfMonth + 3, 2100);
+        sheet.setColumnWidth(dayOfMonth + 4, 2100);
+        sheet.setColumnWidth(dayOfMonth + 5, 1700);
+        sheet.setColumnWidth(dayOfMonth + 6, 2100);
+        sheet.setColumnWidth(dayOfMonth + 7, 1600);
+
+        // 设置行高 15
+        for (int i = 0; i < rowNum; i++) {
+            sheet.getRow(i).setHeightInPoints(15F);
+        }
+    }
+
+    private XSSFWorkbook getWorkbook() {
+        if (workbook == null) {
+            workbook = new XSSFWorkbook();
+        }
+        return this.workbook;
+    }
+
+    /**
+     * 添加合并单元格并添加边框
+     */
+    private void addMergedRegion(Sheet sheet, CellRangeAddress range) {
+        sheet.addMergedRegion(range);
+        // 设置合并单元格的边框
+        RegionUtil.setBorderBottom(BorderStyle.THIN, range, sheet);
+        RegionUtil.setBorderTop(BorderStyle.THIN, range, sheet);
+        RegionUtil.setBorderLeft(BorderStyle.THIN, range, sheet);
+        RegionUtil.setBorderRight(BorderStyle.THIN, range, sheet);
+    }
+
+    /**
+     * 条件格式 3色渐变
+     * 绿 FF63BE7B 黄 FFFFEB84 红 FFF8696B
+     */
+    private void setConditionalFormatting(Sheet sheet, CellRangeAddress rangeAddress) {
+        SheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting();
+        ConditionalFormattingRule rule = conditionalFormatting.createConditionalFormattingColorScaleRule();
+        XSSFColor[] colors = new XSSFColor[] {
+                new XSSFColor(), new XSSFColor(), new XSSFColor()
+        };
+        colors[0].setARGBHex("FF63BE7B");
+        colors[1].setARGBHex("FFFFEB84");
+        colors[2].setARGBHex("FFF8696B");
+
+        rule.getColorScaleFormatting().setColors(colors);
+
+        CellRangeAddress[] cellRangeAddresses = new CellRangeAddress[] {
+                rangeAddress
+        };
+
+        conditionalFormatting.addConditionalFormatting(cellRangeAddresses, rule);
+    }
+
+    /**
+     * 条件格式 3色渐变
+     * 绿 FF63BE7B 黄 FFFFEB84 红 FFF8696B
+     */
+    private void setConditionalFormatting2(Sheet sheet, CellRangeAddress rangeAddress) {
+        SheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting();
+        ConditionalFormattingRule rule = conditionalFormatting.createConditionalFormattingColorScaleRule();
+        XSSFColor[] colors = new XSSFColor[] {
+                new XSSFColor(), new XSSFColor(), new XSSFColor()
+        };
+        colors[0].setARGBHex("FFF8696B");
+        colors[1].setARGBHex("FFFFEB84");
+        colors[2].setARGBHex("FF63BE7B");
+
+        rule.getColorScaleFormatting().setColors(colors);
+
+        CellRangeAddress[] cellRangeAddresses = new CellRangeAddress[] {
+                rangeAddress
+        };
+
+        conditionalFormatting.addConditionalFormatting(cellRangeAddresses, rule);
+    }
+}

+ 14 - 36
src/main/java/com/nokia/tsl_data/service/UserCountService.java

@@ -1,6 +1,5 @@
 package com.nokia.tsl_data.service;
 
-import com.nokia.tsl_data.dao.UserCountMapper;
 import com.nokia.tsl_data.dao.UserCountRepository;
 import com.nokia.tsl_data.entity.UserCount;
 import org.springframework.stereotype.Service;
@@ -18,13 +17,11 @@ import java.util.Map;
 public class UserCountService {
 
     private final UserCountRepository userCountRepository;
-    private final UserCountMapper userCountMapper;
 
     private final DateFormat dateFormat = new SimpleDateFormat("yyyyMM");
 
-    public UserCountService(UserCountRepository userCountRepository, UserCountMapper userCountMapper) {
+    public UserCountService(UserCountRepository userCountRepository) {
         this.userCountRepository = userCountRepository;
-        this.userCountMapper = userCountMapper;
     }
 
     /**
@@ -32,28 +29,10 @@ public class UserCountService {
      * 递归方式,最多递归2层
      */
     public Map<String, Double> getManagementUserCountForMonth(String monthId) {
-        List<Map<String, Object>> managementUserCountForMonth = getManagementUserCountForMonth(monthId, 2);
+        List<UserCount> managementUserCountForMonth = getUserCountForMonth(monthId, 2);
         Map<String, Double> result = new HashMap<>();
-        for (Map<String, Object> map : managementUserCountForMonth) {
-            result.put(map.get("city_name").toString(),
-                    Double.parseDouble(map.get("management_user_count").toString()));
-        }
-        return result;
-    }
-
-    /**
-     * 递归实现getangementUserCountForMonth
-     */
-    private List<Map<String, Object>> getManagementUserCountForMonth(String monthId, int stackLayerCount) {
-        List<Map<String, Object>> result = userCountMapper.selectMangementUserCountForMonth(monthId);
-        if (stackLayerCount != 0) {
-            stackLayerCount -= 1;
-            if (result == null || result.size() == 0) {
-                LocalDate localDate = LocalDate.parse(monthId + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
-                localDate = localDate.plusMonths(-1L);
-                String newMonthId = DateTimeFormatter.ofPattern("yyyyMM").format(localDate);
-                return getManagementUserCountForMonth(newMonthId, stackLayerCount);
-            }
+        for (UserCount userCount : managementUserCountForMonth) {
+            result.put(userCount.getCityName(), userCount.getManagementUserCount());
         }
         return result;
     }
@@ -63,30 +42,29 @@ public class UserCountService {
      * 递归方式,最多递归2层
      */
     public Map<String, Double> getCustomerUserCountForMonth(String monthId) {
-        List<Map<String, Object>> mangementUserCountForMonth = getCustomerUserCountForMonth(monthId, 2);
+        List<UserCount> managementUserCountForMonth = getUserCountForMonth(monthId, 2);
         Map<String, Double> result = new HashMap<>();
-        for (Map<String, Object> map : mangementUserCountForMonth) {
-            result.put(map.get("city_name").toString(),
-                    Double.parseDouble(map.get("customer_user_count").toString()));
+        for (UserCount userCount : managementUserCountForMonth) {
+            result.put(userCount.getCityName(), userCount.getCustomerUserCount());
         }
         return result;
     }
 
     /**
-     * 递归实现getangementUserCountForMonth
+     * 递归实现 getUserCountForMonth
      */
-    private List<Map<String, Object>> getCustomerUserCountForMonth(String monthId, int stackLayerCount) {
-        List<Map<String, Object>> result = userCountMapper.selectCustomerUserCountForMonth(monthId);
-        if (stackLayerCount != 0) {
+    private List<UserCount> getUserCountForMonth(String monthId, int stackLayerCount) {
+        List<UserCount> userCounts = userCountRepository.selectUserCountForMonth(monthId);
+        while (stackLayerCount != 0) {
             stackLayerCount -= 1;
-            if (result == null || result.size() == 0) {
+            if (userCounts == null || userCounts.size() == 0) {
                 LocalDate localDate = LocalDate.parse(monthId + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
                 localDate = localDate.plusMonths(-1L);
                 String newMonthId = DateTimeFormatter.ofPattern("yyyyMM").format(localDate);
-                return getCustomerUserCountForMonth(newMonthId, stackLayerCount);
+                return getUserCountForMonth(newMonthId, stackLayerCount);
             }
         }
-        return result;
+        return userCounts;
     }
 
     /**

+ 18 - 0
src/main/resources/mapper/HighQualityCountMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.nokia.tsl_data.dao.HighQualityCountMapper">
+
+    <!-- 从客户端统计表获取某日的总投诉量(办结量) -->
+    <select id="selectTotalComplaintsForDay" resultType="map">select businoareaname,
+        total_complaints from report_auto.he_d_high_quality hdhq where month_id = substring(#{day}
+        from 1 for 6) and day_id = substring(#{day} from 7 for 2) and profes_dep = '网络质量' and
+        big_type_name = '移网网络体验' and small_type_name = '--'</select>
+
+    <!-- 从客户端统计表获取某日的总投诉量(办结量) 入参 monthId dayId -->
+    <select id="selectTotalComplaintsForMonthIdAndDay" resultType="map">select businoareaname,
+        total_complaints from report_auto.he_d_high_quality hdhq where month_id = #{monthId} and
+        day_id = #{day} and profes_dep = '网络质量' and big_type_name = '移网网络体验' and small_type_name =
+        '--'</select>
+
+</mapper>

+ 0 - 16
src/test/java/com/nokia/tsl_data/MainTest.java

@@ -1,16 +0,0 @@
-package com.nokia.tsl_data;
-
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-
-public class MainTest {
-
-    @Test
-    void test() {
-        File file = new File("C:\\Users\\lfq\\Desktop\\新建文件夹\\HE_D_HIGH_QUALITY_LIST_DAY_1114200095151828992_20231009.csv");
-        System.out.println(file.exists());
-        File file2 = new File(file.getAbsolutePath()+".MD5");
-        System.out.println("==========="+file2.exists());
-    }
-}

+ 24 - 62
src/test/java/com/nokia/tsl_data/TslDataApplicationTest.java

@@ -1,93 +1,55 @@
 package com.nokia.tsl_data;
 
-import com.nokia.common.io.TextUtil;
-import com.nokia.pushmessage.service.PushMessageService;
-import com.nokia.tsl_data.dao.HighQualityListDayMapper;
-import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
-import com.nokia.tsl_data.dao.TaskRecordRepository;
-import com.nokia.tsl_data.dao.TslDataDao;
-import com.nokia.tsl_data.entity.SysDataDictionary;
-import com.nokia.tsl_data.service.CronTaskService;
-import com.nokia.tsl_data.service.DataWarehouseService;
+import com.nokia.tsl_data.service.TslReportService;
 import com.nokia.tsl_data.service.UserCountService;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import java.io.IOException;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.util.List;
 
 @SpringBootTest
 class TslDataApplicationTest {
 
-    @Autowired
-    private HighQualityListDayMapper highQualityListDayMapper;
-
-    @Autowired
-    private SysDataDictionaryRepository sysDataDictionaryRepository;
-
-    @Autowired
-    private TslDataDao tslDataDao;
-
-    @Autowired
-    private DataWarehouseService dataWarehouseService;
-
-    @Autowired
-    private TaskRecordRepository taskRecordRepository;
-
-    @Autowired
-    private CronTaskService cronTaskService;
-
-    @Test
-    void test() {
-        String path = "D:\\src\\不满移网网络服务类型(10+15).csv";
-        List<String> strings = TextUtil.readLines(path, "gbk");
-        for (String name : strings) {
-            SysDataDictionary sysDataDictionary = new SysDataDictionary();
-            sysDataDictionary.setName(name);
-            sysDataDictionary.setTypeName("serv_type_name");
-            sysDataDictionaryRepository.save(sysDataDictionary);
-        }
-    }
-
-    @Test
-    void test2() {
-        cronTaskService.tempTableCleanCronTask();
-    }
-
-    @Autowired(required = false)
-    private PushMessageService pushMessageService;
-
-    @Test
-    void test3() {
-        String accessToken = "b2f1424d6119affaacab614b184f043fcd2c73db2651bb86eff29992d66820bf";
-        String prefix = "CUC:";
-        pushMessageService.sendMarkdownMessage(accessToken, prefix, "abc");
-    }
-
     @Autowired
     private UserCountService userCountService;
 
     /**
-     * 更新管理端用户数
+     * 更新管理端用户数--当前阶段需要修改一下模式
      */
     @Test
     void test1() throws IOException {
         String path = "D:/src/管理端用户数.txt";
-        Files.lines(Paths.get(path), Charset.forName("utf-8"))
+        Files.lines(Paths.get(path), StandardCharsets.UTF_8)
                 .forEach(line -> {
                     String[] split = line.split("\t");
                     System.out.println(split[0] + Double.parseDouble(split[2]));
-                    userCountService.updateCustomerUserCount("202310", split[0], Double.parseDouble(split[2]));
+                    userCountService.updateManagementUserCount("202310", split[0], Double.parseDouble(split[2]));
                 });
     }
 
+    /**
+     * 更新客户端用户数
+     */
     @Test
-    void test4() {
-        List<String> allCityName = sysDataDictionaryRepository.findAllCityName();
-        System.out.println(allCityName);
+    void test2() throws IOException {
+        String path = "D:/src/客户端用户数.txt";
+        Files.lines(Paths.get(path), StandardCharsets.UTF_8)
+                .forEach(line -> {
+                    String[] split = line.split("\t");
+                    System.out.println(split[0] + Double.parseDouble(split[1]));
+                    userCountService.updateCustomerUserCount("202310", split[0], Double.parseDouble(split[1]));
+                });
+    }
+
+    @Autowired
+    private TslReportService tslReportService;
+
+    @Test
+    void test() {
+        tslReportService.workbookToFile("20231014", "D:/src/123");
     }
 }