“lifuquan” 1 rok temu
rodzic
commit
a0f4623b94

+ 7 - 7
doc/开发环境/2023年适配/2024年适配.md

@@ -157,7 +157,7 @@ from t1 group by real_name order by real_name
 POST http://192.168.10.7:22222/tsl_data/report/generate/v3
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2. 数据入库
@@ -168,7 +168,7 @@ Content-Type: application/json
 POST http://192.168.10.7:22222/tsl_data/source/warehouse/mobile_complaint
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2.2 high_quality_count
@@ -177,7 +177,7 @@ Content-Type: application/json
 POST http://192.168.10.7:22222/tsl_data/source/warehouse/high_quality_count
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2.3 high_quality_list
@@ -186,7 +186,7 @@ Content-Type: application/json
 POST http://192.168.10.7:22222/tsl_data/source/warehouse/high_quality_list
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2.4 complaint_details_fix_ywd
@@ -195,7 +195,7 @@ Content-Type: application/json
 POST http://192.168.10.7:22222/tsl_data/source/warehouse/complaint_details_fix_ywd
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2.5 management_detail
@@ -204,7 +204,7 @@ Content-Type: application/json
 POST http://192.168.10.7:22222/tsl_data/source/update/management_detail
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2.6 highQualityData
@@ -213,7 +213,7 @@ Content-Type: application/json
 POST http://192.168.10.7:22222/tsl_data/source/highQualityData/generate
 Content-Type: application/json
 
-20240101
+20240102
 ```
 
 ### 2.7 work_flow_basic_data

+ 5 - 1
doc/需求文档/2024年适配/关于投诉工单日报表2024年适配的需求.md

@@ -60,7 +60,11 @@
 
 如果响应:解决:满意是90%:91%:92%,那这个值就是90%*0.1+91%*0.4+92%*0.5=91.4%
 
-### 7.5 支撑地市日报功能
+### 7.5 发送顺序
+
+顺序还是投诉率、三率、超时、时长
+
+### 7.6 支撑地市日报功能
 
 支撑地市发送日报功能,可实现地市更新区县后,
 

+ 74 - 62
src/main/java/com/nokia/tsl_data/dao/ManagementDetailMapper.java

@@ -12,73 +12,85 @@ import org.apache.ibatis.annotations.Select;
 @Mapper
 public interface ManagementDetailMapper {
 
-    /**
-     * 投诉清单分日期分地市计数 按账期查询
-     */
-    @Select("select compl_area_local, substring(acct_date from 7 for 2) as day_id, count(1) as num " + //
-            " from tsl_data.management_detail\r\n" + //
-            " where stat_day_id = #{day} " + //
-            " group by compl_area_local, substring(acct_date from 7 for 2)\r\n" + //
-            " order by compl_area_local, substring(acct_date from 7 for 2)")
-    List<Map<String, Object>> selectCityTslForMonth(@Param("day") String day);
+        /**
+         * 投诉清单分日期分地市计数 按账期查询
+         */
+        @Select("select compl_area_local, substring(acct_date from 7 for 2) as day_id, count(1) as num " + //
+                        " from tsl_data.management_detail\r\n" + //
+                        " where stat_day_id = #{day} " + //
+                        " group by compl_area_local, substring(acct_date from 7 for 2)\r\n" + //
+                        " order by compl_area_local, substring(acct_date from 7 for 2)")
+        List<Map<String, Object>> selectCityTslForMonth(@Param("day") String day);
 
-    /**
-     * 投诉清单全省分日计数 按账期查询
-     */
-    @Select("select substring(acct_date from 7 for 2) as day_id, count(1) as num" + //
-            " from tsl_data.management_detail\r\n" + //
-            " where stat_day_id = #{day} " + //
-            " group by substring(acct_date from 7 for 2)\r\n" + //
-            " order by substring(acct_date from 7 for 2)")
-    List<Map<String, Object>> selectAllTslForMonth(@Param("day") String day);
+        /**
+         * 投诉清单全省分日计数 按账期查询
+         */
+        @Select("select substring(acct_date from 7 for 2) as day_id, count(1) as num" + //
+                        " from tsl_data.management_detail\r\n" + //
+                        " where stat_day_id = #{day} " + //
+                        " group by substring(acct_date from 7 for 2)\r\n" + //
+                        " order by substring(acct_date from 7 for 2)")
+        List<Map<String, Object>> selectAllTslForMonth(@Param("day") String day);
 
-    /**
-     * 投诉清单地市总数 按账期查询
-     */
-    @Select("select compl_area_local, count(1) as num " + //
-            " from tsl_data.management_detail\r\n" + //
-            " where stat_day_id = #{day} " + //
-            " group by compl_area_local\r\n" + //
-            " order by compl_area_local")
-    List<Map<String, Object>> selectCityAllForMonth(@Param("day") String day);
+        /**
+         * 投诉清单地市总数 按账期查询
+         */
+        @Select("select compl_area_local, count(1) as num " + //
+                        " from tsl_data.management_detail\r\n" + //
+                        " where stat_day_id = #{day} " + //
+                        " group by compl_area_local\r\n" + //
+                        " order by compl_area_local")
+        List<Map<String, Object>> selectCityAllForMonth(@Param("day") String day);
 
-    /**
-     * 全省总数 按账期查询
-     */
-    @Select("select count(1) as num\r\n" + //
-            "from tsl_data.management_detail\r\n" + //
-            "where stat_day_id = #{day} ")
-    int selectAllForMonth(@Param("day") String day);
+        /**
+         * 全省总数 按账期查询
+         */
+        @Select("select count(1) as num\r\n" + //
+                        "from tsl_data.management_detail\r\n" + //
+                        "where stat_day_id = #{day} ")
+        int selectAllForMonth(@Param("day") String day);
 
-    /**
-     * 从 河北_CEM移网质量投诉明细 mobile_complaint_day 中同步数据
-     */
-    @Insert("insert into tsl_data.management_detail (origin, stat_day_id, acct_date, sheet_no," +
-            " compl_area_local, compl_city_local) " +
-            "select 'mobile_complaint_day' as origin, concat(month_id, day_id) as stat_day_id," +
-            " acct_date, sheet_no, compl_area_local, gis_city as compl_city_local " +
-            " from tsl_data.mobile_complaint_day mcd \r\n" +
-            " where month_id = substring(#{day} from 1 for 6) and day_id = substring(#{day} from 7 for 2) ")
-    int insertFromMobileComplaint(@Param("day") String day);
+        /**
+         * 从 河北_CEM移网质量投诉明细 mobile_complaint_day 中同步数据
+         */
+        @Insert("insert into tsl_data.management_detail (origin, stat_day_id, acct_date, sheet_no," +
+                        " compl_area_local, compl_city_local) " +
+                        "select 'mobile_complaint_day' as origin, concat(month_id, day_id) as stat_day_id," +
+                        " acct_date, sheet_no, compl_area_local, gis_city as compl_city_local " +
+                        " from tsl_data.mobile_complaint_day mcd \r\n" +
+                        " where month_id = substring(#{day} from 1 for 6) and day_id = substring(#{day} from 7 for 2) ")
+        int insertFromMobileComplaint(@Param("day") String day);
 
-    /**
-     * 从 河北客户体验管理智能定责投诉明细月累计接口日 complaint_details_fix_ywd_day 同步数据
-     */
-    @Insert("insert into tsl_data.management_detail (origin, stat_day_id, acct_date, sheet_no," +
-            " compl_area_local, compl_city_local) " +
-            "select 'complaint_details_fix_ywd_day' as origin, concat(month_id, day_id) as stat_day_id," +
-            " concat(month_id1, day_id1) as acct_date, sheet_no, compl_area_local, compl_city_local " +
-            " from tsl_data.complaint_details_fix_ywd_day cdfyd \r\n" +
-            " where duty_reason_id_day = '业务使用>>基础业务使用>>移网主被叫>>手机无法主被叫'\r\n" +
-            " and month_id = substring(#{day} from 1 for 6) and day_id = substring(#{day} from 7 for 2) ")
-    int insertFromComplaintDetailsFixYwd(@Param("day") String day);
+        /**
+         * 从 河北客户体验管理智能定责投诉明细月累计接口日 complaint_details_fix_ywd_day 同步数据
+         */
+        @Insert("insert into tsl_data.management_detail (origin, stat_day_id, acct_date, sheet_no," +
+                        " compl_area_local, compl_city_local) " +
+                        "select 'complaint_details_fix_ywd_day' as origin, concat(month_id, day_id) as stat_day_id," +
+                        " concat(month_id1, day_id1) as acct_date, sheet_no, compl_area_local, compl_city_local " +
+                        " from tsl_data.complaint_details_fix_ywd_day cdfyd \r\n" +
+                        " where duty_reason_id_day = '业务使用>>基础业务使用>>移网主被叫>>手机无法主被叫'\r\n" +
+                        " and month_id = substring(#{day} from 1 for 6) and day_id = substring(#{day} from 7 for 2) ")
+        int insertFromComplaintDetailsFixYwd(@Param("day") String day);
 
-    /**
-     * 按照账期统计某个账期的数据量
-     */
-    @Select("select count(1) from tsl_data.management_detail where stat_day_id = #{day} ")
-    int selectCountofStatDay(@Param("day") String day);
+        /**
+         * 按照账期统计某个账期的数据量
+         */
+        @Select("select count(1) from tsl_data.management_detail where stat_day_id = #{day} ")
+        int selectCountofStatDay(@Param("day") String day);
 
-    @Delete("delete from tsl_data.management_detail where tat_day_id = #{day}")
-    int deleteForStatDay(@Param("day") String day);
+        @Delete("delete from tsl_data.management_detail where tat_day_id = #{day}")
+        int deleteForStatDay(@Param("day") String day);
+
+        @Select("with t1 as (select compl_area_local, sheet_no from tsl_data.management_detail md  \n" + //
+                        " where stat_day_id = #{day}), \n" + //
+                        " t2 as (select distinct * from t1), \n" + //
+                        " t3 as (select compl_area_local, count(1) as total_num from t1 group by compl_area_local), \n" + //
+                        " t4 as (select compl_area_local, count(1) as distinct_num from t2 group by compl_area_local), \n"
+                        + " t5 as (select t3.compl_area_local, t3.total_num, t3.total_num - t4.distinct_num::float8 as repeat_num, \n"
+                        + " (t3.total_num - t4.distinct_num) / t3.total_num::float8 as repeat_ratio from T3, t4 \n" + //
+                        " where t3.compl_area_local = t4.compl_area_local) \n" + //
+                        " select '全省' as compl_area_local, sum(total_num) as total_num, sum(repeat_num) as repeat_num, \n"
+                        + " sum(repeat_num) / sum(total_num)::float8 as repeat_ratio from t5 union select * from t5 ")
+        List<Map<String, Object>> selectRepeatTsCountForDay(String day);
 }

+ 54 - 0
src/main/java/com/nokia/tsl_data/service/ManagementDetailService.java

@@ -134,4 +134,58 @@ public class ManagementDetailService {
         }
     }
 
+    /**
+     * 重复投诉
+     */
+    public List<List<Object>> getRepeatTsDataV3(String day) {
+        // 从数据库
+        List<Map<String, Object>> dayData = managementDetailMapper.selectRepeatTsCountForDay(day);
+        List<Map<String, Object>> preDayData = dayData;
+        if (!day.endsWith("01")) {
+            String preDay = String.valueOf(Integer.parseInt(day) - 1);
+            preDayData = managementDetailMapper.selectRepeatTsCountForDay(preDay);
+        }
+        // 转化格式方便读取
+        Map<String, Map<String, Object>> dayMap = new HashMap<>();
+        Map<String, Map<String, Object>> preMap = new HashMap<>();
+        for (Map<String, Object> map : dayData) {
+            dayMap.put((String) map.get("compl_area_local"), map);
+        }
+        for (Map<String, Object> map : preDayData) {
+            preMap.put((String) map.get("compl_area_local"), map);
+        }
+        List<List<Object>> result = new ArrayList<>();
+        // 各地市数据
+        for (String area : sysDataDictionaryRepository.findAllCityName()) {
+            List<Object> list = new ArrayList<>(7);
+            result.add(list);
+            list.add(0, area);
+            // 重复投诉工单数
+            list.add(1, preMap.get(area).get("repeat_num"));
+            list.add(2, dayMap.get(area).get("repeat_num"));
+            // 重复投诉率
+            list.add(3, preMap.get(area).get("repeat_ratio"));
+            list.add(4, dayMap.get(area).get("repeat_ratio"));
+            // 增量
+            list.add(5, ((double) list.get(2)) - ((double) list.get(1)));
+            list.add(6, ((double) list.get(4)) - ((double) list.get(3)));
+        }
+        // 排序--逆序
+        result.sort((o1, o2) -> Double.compare((double) o2.get(6), (double) o1.get(6)));
+        // 全省数据
+        List<Object> list = new ArrayList<>(7);
+        result.add(list);
+        list.add(0, "全省");
+        // 重复投诉工单数
+        list.add(1, preMap.get("全省").get("repeat_num"));
+        list.add(2, dayMap.get("全省").get("repeat_num"));
+        // 重复投诉率
+        list.add(3, preMap.get("全省").get("repeat_ratio"));
+        list.add(4, dayMap.get("全省").get("repeat_ratio"));
+        // 增量
+        list.add(5, ((double) list.get(2)) - ((double) list.get(1)));
+        list.add(6, ((double) list.get(4)) - ((double) list.get(3)));
+        return result;
+    }
+
 }

+ 257 - 8
src/main/java/com/nokia/tsl_data/service/ReportServiceV3.java

@@ -10,6 +10,7 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
 import java.util.Locale;
@@ -40,6 +41,8 @@ import java.awt.image.BufferedImage;
 
 import com.nokia.tsl_data.dao.SysDataDictionaryRepository;
 import com.nokia.tsl_data.entity.pojo.XSSFWorkbookWrapper;
+import com.nokia.tsl_data.util.DateFormatUtil;
+import com.nokia.tsl_data.util.TextUtil;
 import com.nokia.tsl_data.util.excel.PoiUtil;
 import com.nokia.tsl_data.util.excel.entity.CellRect;
 
@@ -62,6 +65,126 @@ public class ReportServiceV3 {
 
     private static final DateFormat DAY_FORMAT = new SimpleDateFormat("yyyyMMdd");
 
+    /**
+     * 每日消息
+     */
+    public void messageToSend(File file, String day) {
+        try (Workbook workbook = WorkbookFactory.create(file)) {
+            StringBuffer stringBuffer = new StringBuffer();
+            Calendar calendar = DateFormatUtil.toCalendar(day, "yyyyMMdd");
+            int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
+            stringBuffer.append(calendar.get(Calendar.YEAR))
+                    .append("年")
+                    .append(calendar.get(Calendar.MONTH) + 1)
+                    .append("月截至")
+                    .append(dayOfMonth)
+                    .append("日移动网投诉情况统计:\n\n");
+            // 管理端-移网感知类
+            Sheet sheet = workbook.getSheet("管理端-移网感知类");
+            Row row;
+            if (sheet != null) {
+                List<List<Object>> list = new ArrayList<>();
+                List<List<Object>> list0 = new ArrayList<>();
+                for (int i = 2; i < 14; i++) {
+                    row = sheet.getRow(i);
+                    double value = row.getCell(dayOfMonth + 6).getNumericCellValue();
+                    List<Object> list2 = new ArrayList<>();
+                    list2.add(0, value);
+                    list2.add(1, row.getCell(dayOfMonth + 7).getStringCellValue());
+                    if (value > 0.0) {
+                        list.add(list2);
+                    }
+                    list0.add(list2);
+                }
+                // 排序
+                list.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
+                list0.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
+                stringBuffer.append("管理端-移网感知类:");
+                if (list.size() == 0) {
+                    stringBuffer.append("投诉率:12个地市均已达标,<font color=#FF0000>");
+                } else {
+                    stringBuffer.append("投诉率:<font color=#FF0000>");
+                    for (int i = 0; i < list.size(); i++) {
+                        stringBuffer.append(list.get(i).get(1).toString()).append("、");
+                    }
+                    stringBuffer.deleteCharAt(stringBuffer.length() - 1);
+                    stringBuffer.append("</font>未达到目标值,<font color=#FF0000>");
+                }
+                StringBuffer stringBuffer2 = new StringBuffer();
+                for (int i = 0; i < 3; i++) {
+                    stringBuffer2.append(list0.get(i).get(1).toString()).append("、");
+                }
+                stringBuffer2.deleteCharAt(stringBuffer2.length() - 1);
+                stringBuffer.append(stringBuffer2.toString()).append("</font>排名靠后。");
+            }
+            // 管理端-重复投诉率
+            sheet = workbook.getSheet("管理端-重复投诉率");
+            if (sheet == null || day.endsWith("01")) {
+                // 1号忽略重复投诉率
+                stringBuffer.append("\n\n");
+            } else {
+                stringBuffer.append("重复投诉率:<font color=#FF0000>");
+                stringBuffer.append(sheet.getRow(3).getCell(0).getStringCellValue()).append("、")
+                        .append(sheet.getRow(4).getCell(0).getStringCellValue()).append("、")
+                        .append(sheet.getRow(5).getCell(0).getStringCellValue())
+                        .append("</font>增长较快。\n\n");
+            }
+            // 移网综合投诉评价
+            sheet = workbook.getSheet("移网综合投诉评价");
+            if (sheet != null) {
+                stringBuffer.append("移网综合投诉评价:<font color=#FF0000>");
+                for (int i = 2; i < 14; i++) {
+                    if (sheet.getRow(i).getCell(6).getNumericCellValue() > 0.0d) {
+                        stringBuffer.append(sheet.getRow(i).getCell(0).getStringCellValue());
+                    } else {
+                        break;
+                    }
+                    stringBuffer.append("、");
+                }
+                stringBuffer.append("</font>未达到目标值。\n\n");
+            }
+            // 投诉处理时长、超时工单概况
+            sheet = workbook.getSheet("投诉处理时长、超时工单概况");
+            if (sheet != null) {
+                stringBuffer.append("投诉处理时长、超时工单概况:超时工单:<font color=#FF0000>")
+                        .append(sheet.getRow(2).getCell(0).getStringCellValue()).append("、")
+                        .append(sheet.getRow(3).getCell(0).getStringCellValue()).append("、")
+                        .append(sheet.getRow(4).getCell(0).getStringCellValue())
+                        .append("</font>分公司超时工单占比较高,<font color=#FF0000>");
+                List<List<Object>> list = new ArrayList<>();
+                for (int i = 2; i < 14; i++) {
+                    List<Object> list2 = new ArrayList<>();
+                    list.add(list2);
+                    list2.add(0, sheet.getRow(i).getCell(2).getNumericCellValue());
+                    list2.add(1, sheet.getRow(i).getCell(0).getStringCellValue());
+                }
+                list.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
+                stringBuffer.append(list.get(0).get(1).toString()).append("、")
+                        .append(list.get(1).get(1).toString()).append("、")
+                        .append(list.get(2).get(1).toString())
+                        .append("</font>超时工单数量较多。平均处理时长:本月相对较长的地市为<font color=#FF0000>");
+
+                list = new ArrayList<>();
+                for (int i = 2; i < 14; i++) {
+                    List<Object> list2 = new ArrayList<>();
+                    list.add(list2);
+                    list2.add(0, sheet.getRow(i).getCell(8).getNumericCellValue());
+                    list2.add(1, sheet.getRow(i).getCell(6).getStringCellValue());
+                }
+                list.sort((o1, o2) -> Double.compare((double) o2.get(0), (double) o1.get(0)));
+                stringBuffer.append(list.get(0).get(1).toString()).append("、")
+                        .append(list.get(1).get(1).toString()).append("、")
+                        .append(list.get(2).get(1).toString()).append("</font>;与")
+                        .append(sheet.getRow(1).getCell(7).getStringCellValue()).append("比<font color=#FF0000>")
+                        .append(sheet.getRow(2).getCell(6).getStringCellValue()).append("</font>时长增幅较大。");
+            }
+            TextUtil.writeToFileWithUTF8(stringBuffer.toString(), Paths.get(file.getParent(), "总结.txt").toString());
+        } catch (IOException e) {
+            log.error("读取excel文件出错:{}", e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
     /**
      * 截图
      */
@@ -80,20 +203,28 @@ public class ReportServiceV3 {
                 area = "A1:" + CellRect.getColumnName(dayOfMonth + 7) + "15";
                 screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                 ImageIO.write(screenShot, "png",
-                        Paths.get(file.getParentFile().getAbsolutePath(), "管理端-移网感知类" + day + ".png").toFile());
+                        Paths.get(file.getParentFile().getAbsolutePath(), "管理端-移网感知类-" + day + ".png").toFile());
             }
             // 截图 服请
-            // 截图 重复投诉 超时工单
+            // 截图 重复投诉
+            sheet = workbook.getSheet("管理端-重复投诉率");
+            if (sheet != null) {
+                area = "A1:G16";
+                screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
+                ImageIO.write(screenShot, "png",
+                        Paths.get(file.getParentFile().getAbsolutePath(), "管理端-重复投诉率-" + day + ".png").toFile());
+            }
+            // 截图 处理时长 超时工单
             sheet = workbook.getSheet("投诉处理时长、超时工单概况");
             if (sheet != null) {
                 area = "A1:D15";
                 screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                 ImageIO.write(screenShot, "png",
-                        Paths.get(file.getParentFile().getAbsolutePath(), "超时工单概况" + day + ".png").toFile());
-                area = "G1:J14";
+                        Paths.get(file.getParentFile().getAbsolutePath(), "超时工单概况-" + day + ".png").toFile());
+                area = "G1:J15";
                 screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                 ImageIO.write(screenShot, "png",
-                        Paths.get(file.getParentFile().getAbsolutePath(), "投诉处理时长" + day + ".png").toFile());
+                        Paths.get(file.getParentFile().getAbsolutePath(), "投诉处理时长-" + day + ".png").toFile());
             }
             // 截图 移网综合投诉评价
             sheet = workbook.getSheet("移网综合投诉评价");
@@ -101,7 +232,7 @@ public class ReportServiceV3 {
                 area = "A1:G15";
                 screenShot = PoiUtil.screenShot(sheet, area, "微软雅黑");
                 ImageIO.write(screenShot, "png",
-                        Paths.get(file.getParentFile().getAbsolutePath(), "移网综合投诉评价" + day + ".png").toFile());
+                        Paths.get(file.getParentFile().getAbsolutePath(), "移网综合投诉评价-" + day + ".png").toFile());
             }
         } catch (EncryptedDocumentException | IOException e) {
             e.printStackTrace();
@@ -120,10 +251,12 @@ public class ReportServiceV3 {
         writeSheet1(workbookWrapper, day);
         log.info("帐期 {} 管理端-移网感知类 sheet写入成功", day);
         // 1.2 写入 服请情况
-        // 1.3 写入 投诉处理时长、超时工单概况
+        // 1.3 管理端-重复投诉率
+        writeSheetRepeatTs(workbookWrapper, day);
+        // 1.4 写入 投诉处理时长、超时工单概况
         writeSheet3(workbookWrapper, day);
         log.info("帐期 {} 投诉处理时长、超时工单概况 sheet写入成功", day);
-        // 1.4 写入三率
+        // 1.5 写入三率
         tslDataService.checkStatDayCount(day);
         writeSheet4(workbookWrapper, day);
         log.info("帐期 {} 客户端-三率 sheet写入成功", day);
@@ -139,6 +272,122 @@ public class ReportServiceV3 {
         }
     }
 
+    /**
+     * 管理端-重复投诉率
+     */
+    private void writeSheetRepeatTs(XSSFWorkbookWrapper workbookWrapper, 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 = workbookWrapper.getWorkbook().createSheet("管理端-重复投诉率");
+        Row row;
+        Cell cell;
+        // 第一行 标题栏
+        row = sheet.createRow(0);
+        cell = row.createCell(0);
+        cell.setCellValue(String.format("重复投诉率(1-%s)", dayOfMonth));
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        // 合并单元格 A1 - G1
+        PoiUtil.addMergedRegion(sheet, 0, 0, 0, 6);
+        // 第二行
+        row = sheet.createRow(1);
+        cell = row.createCell(0);
+        cell.setCellValue("");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(1);
+        cell.setCellValue("工单数");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        // 合并单元格 B2-C2
+        PoiUtil.addMergedRegion(sheet, 1, 1, 1, 2);
+        cell = row.createCell(3);
+        cell.setCellValue("重复投诉率");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        // 合并单元格 B2-C2
+        PoiUtil.addMergedRegion(sheet, 1, 1, 3, 4);
+        cell = row.createCell(5);
+        cell.setCellValue("增量");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        // 合并单元格 F2-G2
+        PoiUtil.addMergedRegion(sheet, 1, 1, 5, 6);
+        // 第三行
+        row = sheet.createRow(2);
+        cell = row.createCell(0);
+        cell.setCellValue("地市");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(1);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(2);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(3);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, preDayOfMonth));
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(4);
+        cell.setCellValue(String.format("%s月截止%s日", monthOfYear, dayOfMonth));
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(5);
+        cell.setCellValue("工单数");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        cell = row.createCell(6);
+        cell.setCellValue("重复投诉率");
+        cell.setCellStyle(workbookWrapper.getCellStyle3());
+        // 从数据库读取 客户端 重复投诉数据
+        List<List<Object>> sheet2Data = managementDetailService.getRepeatTsDataV3(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(workbookWrapper.getCellStyle1());
+            // 前一天重复工单数
+            cell = row.createCell(1);
+            cell.setCellValue(((double) list.get(1)));
+            cell.setCellStyle(workbookWrapper.getCellStyle1());
+            // 当天重复工单数
+            cell = row.createCell(2);
+            cell.setCellValue(((double) list.get(2)));
+            cell.setCellStyle(workbookWrapper.getCellStyle1());
+            // 前一天重复投诉率
+            cell = row.createCell(3);
+            cell.setCellValue(((double) list.get(3)));
+            cell.setCellStyle(workbookWrapper.getCellStyle2());
+            // 当前重复投诉率
+            cell = row.createCell(4);
+            cell.setCellValue(((double) list.get(4)));
+            cell.setCellStyle(workbookWrapper.getCellStyle2());
+            // 重复工单增量
+            cell = row.createCell(5);
+            cell.setCellValue(((double) list.get(5)));
+            cell.setCellStyle(workbookWrapper.getCellStyle1());
+            // 重复投诉率增量
+            cell = row.createCell(6);
+            cell.setCellValue(((double) list.get(6)));
+            cell.setCellStyle(workbookWrapper.getCellStyle2());
+        }
+        // 添加条件格式F4-F15
+        PoiUtil.setConditionalFormattingRedToGreen(sheet, 3, 14, 5, 5);
+        // 添加条件格式G4-G15
+        PoiUtil.setConditionalFormattingRedToGreen(sheet, 3, 14, 6, 6);
+        // 设置列宽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);
+        }
+    }
+
     /**
      * 移网综合投诉评价
      */

+ 2 - 0
src/main/java/com/nokia/tsl_data/service/TaskService.java

@@ -133,6 +133,8 @@ public class TaskService {
         reportServiceV3.generateReport(file, day);
         // 3. 截图
         reportServiceV3.screenShot(file, day);
+        // 4. 总结
+        reportServiceV3.messageToSend(file, day);
     }
 
     /**

+ 6 - 5
src/test/java/com/nokia/tsl_data/TslDataApplicationTest.java

@@ -1,11 +1,11 @@
 package com.nokia.tsl_data;
 
-import java.util.Date;
+import java.io.File;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
-import com.nokia.tsl_data.dao.WorkFlowBasicDataMapper;
+import com.nokia.tsl_data.service.ReportServiceV3;
 import com.nokia.tsl_data.service.TaskService;
 
 @SpringBootTest
@@ -16,14 +16,15 @@ class TslDataApplicationTest {
 
     @Test
     void test() {
-        taskService.generateReportV3("20240101");
+        taskService.generateReportV3("20240102");
     }
 
     @Autowired
-    private WorkFlowBasicDataMapper workFlowBasicDataMapper;
+    private ReportServiceV3 reportServiceV3;
 
     @Test
     void test1() {
-        workFlowBasicDataMapper.selectTsDurationForDay(new Date(), new Date());
+        File file = new File("/home/lfq/Documents/code/tsl-data/output/V3/20240102/投诉清单各地市投诉率20240102.xlsx");
+        reportServiceV3.messageToSend(file, "20240102");
     }
 }