Parcourir la source

20240313 增加过滤条件 客服工单号不以 ZHX 开头

lifuquan il y a 10 mois
Parent
commit
c525fd9b7a

+ 12 - 5
doc/部署环境/手动入库数据.md

@@ -14,21 +14,28 @@ Content-Type:application/json
 ## 手动生成报表
 
 ```http
-POST http://192.168.10.7:29100/tsl/task/report/generate HTTP/1.1
+POST http://192.168.10.7:22222/tsl_data/report/generate/v3 HTTP/1.1
 Content-Type:application/json
 
-20231022
+20240310
 ```
 
 ## 数据手动入库
 
-- 两个表一起
+- cem_mobile_experience_list
 
 ```http
-POST http://192.168.10.7:29100/tsl/task/warahouse HTTP/1.1
+POST http://192.168.10.7:22222/tsl_data/source/warehouse/cem_mobile_experience_list HTTP/1.1
 Content-Type:application/json
 
-20231022
+20240310
+```
+
+```http
+POST http://192.168.10.7:22222/tsl_data/source/delete/cem_mobile_experience_list HTTP/1.1
+Content-Type:application/json
+
+20240310
 ```
 
 - report_auto.he_d_mobile_comp

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

@@ -45,7 +45,7 @@
 1. 数据源修改为进入工单流程系统(TOP)的工单。
     - 排除已退单(re_is_status)状态的工单
     - 统计范围为所有存在归档时间的工单
-2. 处理时长 = 客服受理时间 - 客服受理时间,处理时长超过36小时为超时。
+2. 处理时长 = 客服归档时间 - 客服受理时间,处理时长超过36小时为超时。
 3. 月底未回单的工单要计入下月工单--所以应该按归档时间计算工单范围
 
 处理时长,30小时是达标,30-36小时线性扣分

+ 229 - 171
src/main/java/com/nokia/tsl_data/dao/WorkFlowDao.java

@@ -23,175 +23,233 @@ import java.util.Map;
 @Component
 public class WorkFlowDao {
 
-    private final JdbcTemplate jdbcTemplate;
-
-    public WorkFlowDao(@Qualifier("workFlowJdbcTemplate") JdbcTemplate jdbcTemplate) {
-        this.jdbcTemplate = jdbcTemplate;
-    }
-
-    // 获取全部地市信息
-    public List<SysDataDictionary> findSysDataDictionaryForCity() {
-        return findSysDataDictionaries("city");
-    }
-
-    // 获取全部区县信息
-    public List<SysDataDictionary> findSysDataDictionaryForRegion() {
-        return findSysDataDictionaries("region");
-    }
-
-    // 读取某种类型的字典表
-    public List<SysDataDictionary> findSysDataDictionaries(String type) {
-        String sql = "select id, name, type_code from sys_data_dictionary sdd where type_code = ? ";
-        return jdbcTemplate.query(sql,
-                (ps) -> {
-                    ps.setString(1, type);
-                },
-                (rs, rowNum) -> {
-                    SysDataDictionary sysDataDictionary = new SysDataDictionary();
-                    sysDataDictionary.setType("work_flow_" + rs.getString("type_code"));
-                    sysDataDictionary.setNickCode(rs.getString("id"));
-                    sysDataDictionary.setNickName(rs.getString("name"));
-                    return sysDataDictionary;
-                });
-    }
-
-    // 获取update_time在两个范围之间的全部工单信息
-    // 20240205 不再使用
-    @Deprecated
-    public List<Map<String, Object>> findWorkFlowBasicDataByUpdateTime(Instant start, Instant end) {
-        // 20240112 修改 使用 serv_order 替换了kfsn
-        String sql = "select order_no, " + //
-                "city as city_id, " + //
-                "is_effctive as is_effctive, " + //
-                "form_basic_data->>'yh_region' as region_id, " + //
-                "form_basic_data->>'serv_order' as kfsn, " + //
-                "form_basic_data->>'kd_accepttime' as kd_accepttime, " + //
-                "form_basic_data->>'kd_requestreplytime' as kd_requestreplytime, " + //
-                "form_basic_data->>'re_is_status' as re_is_status_id, " + //
-                "form_basic_data->>'kf_file_time' as kf_file_time, " + //
-                "form_basic_data->>'kf_file_type' as kf_file_type, " + //
-                "create_time as work_flow_create_time,  " + //
-                "update_time as work_flow_update_time " + //
-                "from flow_form_basic " + //
-                "where update_time >= to_timestamp(?, 'yyyy-mm-dd hh24:mi:ss') " + //
-                "and update_time <= to_timestamp(?, 'yyyy-mm-dd hh24:mi:ss') ";
-        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
-                .withZone(ZoneId.of("Asia/Shanghai"));
-        Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
-        int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
-        return jdbcTemplate.queryForList(sql, objects, argTypes);
-    }
-
-    /**
-     * 直接从工作流读取处理时长数据
-     */
-    public List<Map<String, Object>> selectTsDurationBasicData(Instant start, Instant end) {
-        String sql = "explain with t1 as (select city as city_id, \r\n" + //
-                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
-                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS')) -\r\n" + //
-                "extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS'))) /\r\n" + //
-                "3600 as cost_time \r\n" + //
-                "from flow_form_basic\r\n" + //
-                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb' \r\n" + //
-                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
-                "and is_effctive = '1'\r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ? \r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < ? \r\n" + //
-                "select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn";
-        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
-                .withZone(ZoneId.of("Asia/Shanghai"));
-        Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
-        int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
-        Long startLong = System.currentTimeMillis();
-        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
-        log.debug("从工作流读取处理时长数据, 耗时 {} ms...", System.currentTimeMillis() - startLong);
-        return result;
-    }
-
-    public List<Map<String, Object>> selectTsDurationForDay(Instant start, Instant end) {
-        String sql = "with t1 as (select city as city_id, \r\n" + //
-                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
-                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS'))\r\n" + //
-                "- extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS')))\r\n" + //
-                "/ 3600 as cost_time \r\n" + //
-                "from flow_form_basic\r\n" + //
-                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
-                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
-                "and is_effctive = '1'\r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ?\r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < ?),\r\n" + //
-                "t2 as (select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn),\r\n" + //
-                "t3 as (select city_id, avg(cost_time)::float8 as avg_duration from t2 group by city_id),\r\n" + //
-                "t4 as (select '全省' as city_id, avg(cost_time)::float8 as avg_duration from t2)\r\n" + //
-                "select * from  t3 union select * from t4";
-        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
-                .withZone(ZoneId.of("Asia/Shanghai"));
-        Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
-        int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
-        Long startLong = System.currentTimeMillis();
-        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
-        log.debug("从工作流读取{}-{}平均处理时长数据, 耗时 {} ms...",
-                start,
-                end,
-                System.currentTimeMillis() - startLong);
-        return result;
-    }
-
-    public List<Map<String, Object>> selectTimeoutTsCountForDay(Instant start, Instant end, int target) {
-        String sql = "with t1 as (select distinct city as city_id, \r\n" + //
-                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
-                "to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') - \r\n" + //
-                "to_timestamp(form_basic_data->>'kd_accepttime', 'yyyy-mm-dd hh24:mi:ss') \r\n" + //
-                "> make_interval(hours => ?) as is_timeout \r\n" + //
-                "from flow_form_basic\r\n" + //
-                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
-                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
-                "and is_effctive = '1'\r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ?\r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') <= ?),\r\n" + //
-                "t2 as (select '全省' as city_id, count(1) as total_num, count(is_timeout or null) as timeout_num,\r\n" + //
-                "count(is_timeout or null)::float8 / count(1) as timeout_ratio from t1),\r\n" + //
-                "t3 as (select city_id, count(1) as total_num, count(is_timeout or null) as timeout_num,\r\n" + //
-                "count(is_timeout or null)::float8 / count(1) as timeout_ratio from t1 group by city_id)\r\n" + //
-                "select * from  t2 union select * from t3";
-        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
-                .withZone(ZoneId.of("Asia/Shanghai"));
-        Object[] objects = new Object[] { target, dateFormat.format(start), dateFormat.format(end) };
-        int[] argTypes = new int[] { Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP };
-        Long startLong = System.currentTimeMillis();
-        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
-        log.debug("从工作流读取{}-{}超时工单数据, 耗时 {} ms...",
-                start,
-                end,
-                System.currentTimeMillis() - startLong);
-        return result;
-    }
-
-    public List<Map<String, Object>> selectTsDurationForMonth(String month) {
-        String sql = "with t1 as (select city as city_id, \r\n" + //
-                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
-                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS'))\r\n" + //
-                "- extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS')))\r\n" + //
-                "/ 3600 as cost_time \r\n" + //
-                "from flow_form_basic\r\n" + //
-                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
-                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
-                "and is_effctive = '1'\r\n" + //
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= " +
-                "to_timestamp(concat(?, '01000000'), 'yyyymmddhh24miss') " +
-                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < " +
-                "(to_timestamp(concat(?, '01000000'), 'yyyymmddhh24miss') + interval '1 month'))," +
-                "t2 as (select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn),\r\n" + //
-                "t3 as (select ? as month_id, city_id, avg(cost_time)::float8 as avg_duration from t2 group by city_id),"
-                + "t4 as (select ? as month_id, '全省' as city_id, avg(cost_time)::float8 as avg_duration from t2)" +
-                "select * from  t3 union select * from t4";
-        Object[] objects = new Object[] { month, month, month, month };
-        int[] argTypes = new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };
-        Long startLong = System.currentTimeMillis();
-        List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
-        log.debug("从工作流读取{}月平均处理时长数据, 耗时 {} ms...",
-                month,
-                System.currentTimeMillis() - startLong);
-        return result;
-    }
+        private final JdbcTemplate jdbcTemplate;
+
+        public WorkFlowDao(@Qualifier("workFlowJdbcTemplate") JdbcTemplate jdbcTemplate) {
+                this.jdbcTemplate = jdbcTemplate;
+        }
+
+        // 获取全部地市信息
+        public List<SysDataDictionary> findSysDataDictionaryForCity() {
+                return findSysDataDictionaries("city");
+        }
+
+        // 获取全部区县信息
+        public List<SysDataDictionary> findSysDataDictionaryForRegion() {
+                return findSysDataDictionaries("region");
+        }
+
+        // 读取某种类型的字典表
+        public List<SysDataDictionary> findSysDataDictionaries(String type) {
+                String sql = "select id, name, type_code from sys_data_dictionary sdd where type_code = ? ";
+                return jdbcTemplate.query(sql,
+                                (ps) -> {
+                                        ps.setString(1, type);
+                                },
+                                (rs, rowNum) -> {
+                                        SysDataDictionary sysDataDictionary = new SysDataDictionary();
+                                        sysDataDictionary.setType("work_flow_" + rs.getString("type_code"));
+                                        sysDataDictionary.setNickCode(rs.getString("id"));
+                                        sysDataDictionary.setNickName(rs.getString("name"));
+                                        return sysDataDictionary;
+                                });
+        }
+
+        // 获取update_time在两个范围之间的全部工单信息
+        // 20240205 不再使用
+        @Deprecated
+        public List<Map<String, Object>> findWorkFlowBasicDataByUpdateTime(Instant start, Instant end) {
+                // 20240112 修改 使用 serv_order 替换了kfsn
+                String sql = "select order_no, " + //
+                                "city as city_id, " + //
+                                "is_effctive as is_effctive, " + //
+                                "form_basic_data->>'yh_region' as region_id, " + //
+                                "form_basic_data->>'serv_order' as kfsn, " + //
+                                "form_basic_data->>'kd_accepttime' as kd_accepttime, " + //
+                                "form_basic_data->>'kd_requestreplytime' as kd_requestreplytime, " + //
+                                "form_basic_data->>'re_is_status' as re_is_status_id, " + //
+                                "form_basic_data->>'kf_file_time' as kf_file_time, " + //
+                                "form_basic_data->>'kf_file_type' as kf_file_type, " + //
+                                "create_time as work_flow_create_time,  " + //
+                                "update_time as work_flow_update_time " + //
+                                "from flow_form_basic " + //
+                                "where update_time >= to_timestamp(?, 'yyyy-mm-dd hh24:mi:ss') " + //
+                                "and update_time <= to_timestamp(?, 'yyyy-mm-dd hh24:mi:ss') ";
+                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                                .withZone(ZoneId.of("Asia/Shanghai"));
+                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
+                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
+                return jdbcTemplate.queryForList(sql, objects, argTypes);
+        }
+
+        /**
+         * 直接从工作流读取处理时长数据
+         */
+        @Deprecated
+        public List<Map<String, Object>> selectTsDurationBasicData(Instant start, Instant end) {
+                String sql = "with t1 as (select city as city_id, \r\n" + //
+                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
+                                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS')) -\r\n"
+                                + //
+                                "extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS'))) /\r\n"
+                                + //
+                                "3600 as cost_time \r\n" + //
+                                "from flow_form_basic\r\n" + //
+                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb' \r\n" + //
+                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
+                                "and is_effctive = '1'\r\n" + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ? \r\n"
+                                + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < ? \r\n" + //
+                                "select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn";
+                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                                .withZone(ZoneId.of("Asia/Shanghai"));
+                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
+                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
+                Long startLong = System.currentTimeMillis();
+                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
+                log.debug("从工作流读取处理时长数据, 耗时 {} ms...", System.currentTimeMillis() - startLong);
+                return result;
+        }
+
+        // 20240304 修改平均处理时长算法
+        // 20240313 增加过滤条件 客服工单号不以 ZHX 开头
+        public List<Map<String, Object>> selectTsDurationForDayV2(String start, String end) {
+                String sql = "with t1 as (select order_no, city as city_id, form_basic_data->>'serv_order' as kfsn " +
+                                ", form_basic_data->>'kd_accepttime' as kd_accepttime " +
+                                "from flow_form_basic where is_effctive = '1' " +
+                                "and substring(form_basic_data->>'serv_order' from 1 for 3) != 'ZHX' " +
+                                "and create_time >= ? and create_time <= ? " +
+                                "and form_basic_data->>'kd_accepttime' >= ? " +
+                                "and form_basic_data->>'kd_accepttime' <= ?) " +
+                                ", t2 as (select order_no, res_date " +
+                                "from complaint.kf_log), " +
+                                "t3 as (select t1.order_no, t1.city_id, t1.kfsn," +
+                                "extract(epoch from coalesce(to_timestamp(max(t2.res_date), 'yyyy-mm-dd hh24:mi:ss'), now())) "
+                                +
+                                "- extract(epoch from to_timestamp(min(t1.kd_accepttime), 'yyyy-mm-dd hh24:mi:ss')) as cost_time "
+                                +
+                                "from t1 left join t2 " +
+                                "on t1.order_no = t2.order_no " +
+                                "group by t1.order_no, t1.city_id, t1.kfsn) " +
+                                ", t4 as (select city_id, kfsn, min(cost_time) as cost_time from t3 group by city_id, kfsn) "
+                                +
+                                ", t5 as (select city_id, avg(cost_time)::float8/3600 as avg_duration from t4 group by city_id) "
+                                +
+                                ", t6 as (select '全省', avg(cost_time)::float8/3600 as avg_duration from t4) " +
+                                "select * from t5 union select * from t6";
+                Object[] objects = new Object[] { start, end, start, end };
+                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP };
+                Long startLong = System.currentTimeMillis();
+                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
+                log.debug("从工作流读取{}-{}平均处理时长数据, 耗时 {} ms, sql: {}",
+                                start,
+                                end,
+                                System.currentTimeMillis() - startLong,
+                                sql);
+                return result;
+        }
+
+        // 20240304 之前获取平均处理时长的sql语句
+        @Deprecated
+        public List<Map<String, Object>> selectTsDurationForDay(Instant start, Instant end) {
+                String sql = "with t1 as (select city as city_id, \r\n" + //
+                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
+                                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS'))\r\n"
+                                + //
+                                "- extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS')))\r\n"
+                                + //
+                                "/ 3600 as cost_time \r\n" + //
+                                "from flow_form_basic\r\n" + //
+                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
+                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
+                                "and is_effctive = '1'\r\n" + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ?\r\n" + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < ?),\r\n"
+                                + //
+                                "t2 as (select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn),\r\n"
+                                + //
+                                "t3 as (select city_id, avg(cost_time)::float8 as avg_duration from t2 group by city_id),\r\n"
+                                + //
+                                "t4 as (select '全省' as city_id, avg(cost_time)::float8 as avg_duration from t2)\r\n" + //
+                                "select * from  t3 union select * from t4";
+                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                                .withZone(ZoneId.of("Asia/Shanghai"));
+                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
+                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
+                Long startLong = System.currentTimeMillis();
+                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
+                log.debug("从工作流读取{}-{}平均处理时长数据, 耗时 {} ms...",
+                                start,
+                                end,
+                                System.currentTimeMillis() - startLong);
+                return result;
+        }
+
+        public List<Map<String, Object>> selectTimeoutTsCountForDay(Instant start, Instant end, int target) {
+                String sql = "with t1 as (select distinct city as city_id, \r\n" + //
+                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
+                                "to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') - \r\n" + //
+                                "to_timestamp(form_basic_data->>'kd_accepttime', 'yyyy-mm-dd hh24:mi:ss') \r\n" + //
+                                "> make_interval(hours => ?) as is_timeout \r\n" + //
+                                "from flow_form_basic\r\n" + //
+                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
+                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
+                                "and is_effctive = '1'\r\n" + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ?\r\n" + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') <= ?),\r\n"
+                                + //
+                                "t2 as (select '全省' as city_id, count(1) as total_num, count(is_timeout or null) as timeout_num,\r\n"
+                                + //
+                                "count(is_timeout or null)::float8 / count(1) as timeout_ratio from t1),\r\n" + //
+                                "t3 as (select city_id, count(1) as total_num, count(is_timeout or null) as timeout_num,\r\n"
+                                + //
+                                "count(is_timeout or null)::float8 / count(1) as timeout_ratio from t1 group by city_id)\r\n"
+                                + //
+                                "select * from  t2 union select * from t3";
+                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                                .withZone(ZoneId.of("Asia/Shanghai"));
+                Object[] objects = new Object[] { target, dateFormat.format(start), dateFormat.format(end) };
+                int[] argTypes = new int[] { Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP };
+                Long startLong = System.currentTimeMillis();
+                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
+                log.debug("从工作流读取{}-{}超时工单数据, 耗时 {} ms...",
+                                start,
+                                end,
+                                System.currentTimeMillis() - startLong);
+                return result;
+        }
+
+        @Deprecated
+        public List<Map<String, Object>> selectTsDurationForMonth(String month) {
+                String sql = "with t1 as (select city as city_id, \r\n" + //
+                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
+                                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS'))\r\n"
+                                + //
+                                "- extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS')))\r\n"
+                                + //
+                                "/ 3600 as cost_time \r\n" + //
+                                "from flow_form_basic\r\n" + //
+                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
+                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
+                                "and is_effctive = '1'\r\n" + //
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= " +
+                                "to_timestamp(concat(?, '01000000'), 'yyyymmddhh24miss') " +
+                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < " +
+                                "(to_timestamp(concat(?, '01000000'), 'yyyymmddhh24miss') + interval '1 month'))," +
+                                "t2 as (select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn),\r\n"
+                                + //
+                                "t3 as (select ? as month_id, city_id, avg(cost_time)::float8 as avg_duration from t2 group by city_id),"
+                                + "t4 as (select ? as month_id, '全省' as city_id, avg(cost_time)::float8 as avg_duration from t2)"
+                                +
+                                "select * from  t3 union select * from t4";
+                Object[] objects = new Object[] { month, month, month, month };
+                int[] argTypes = new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };
+                Long startLong = System.currentTimeMillis();
+                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
+                log.debug("从工作流读取{}月平均处理时长数据, 耗时 {} ms...",
+                                month,
+                                System.currentTimeMillis() - startLong);
+                return result;
+        }
 }

+ 12 - 3
src/main/java/com/nokia/tsl_data/service/WorkFlowService.java

@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
+import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
@@ -87,7 +88,7 @@ public class WorkFlowService {
 
     /**
      * 平均处理时长
-     * 20240205更新
+     * 20240205更新 20240304更新
      */
     public List<List<Object>> getCostTimeInfo(String day) {
         Calendar calendar = Calendar.getInstance(Locale.CHINA);
@@ -178,7 +179,10 @@ public class WorkFlowService {
 
     private List<Map<String, Object>> getTsDurationForDay(Instant start, Instant end) {
         Map<String, String> workFlowCityMap = sysDataDictionaryRepository.findWorkFlowCityMap();
-        List<Map<String, Object>> selectTsDurationForDay = workFlowDao.selectTsDurationForDay(start, end);
+        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                .withZone(ZoneId.of("Asia/Shanghai"));
+        List<Map<String, Object>> selectTsDurationForDay = workFlowDao
+                .selectTsDurationForDayV2(dateFormat.format(start), dateFormat.format(end));
         for (Map<String, Object> map : selectTsDurationForDay) {
             String city_id = (String) map.get("city_id");
             if (city_id.equals("全省")) {
@@ -192,8 +196,13 @@ public class WorkFlowService {
 
     public List<Map<String, Object>> getTsDurationForMonth(String month) {
         Map<String, String> workFlowCityMap = sysDataDictionaryRepository.findWorkFlowCityMap();
-        List<Map<String, Object>> result = workFlowDao.selectTsDurationForMonth(month);
+        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
+                .withZone(ZoneId.of("Asia/Shanghai"));
+        String start = month.substring(0, 4) + "-" + month.substring(4, 6) + "-01 00:00:00";
+        String end = LocalDateTime.parse(start, dateFormat).plusMonths(1).format(dateFormat);
+        List<Map<String, Object>> result = workFlowDao.selectTsDurationForDayV2(start, end);
         for (Map<String, Object> map : result) {
+            map.put("month_id", month);
             String city_id = (String) map.get("city_id");
             if (city_id.equals("全省")) {
                 map.put("city", "全省");

+ 16 - 12
src/test/java/com/nokia/tsl_data/TslDataApplicationTest.java

@@ -5,8 +5,9 @@ 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.TargetTsRatioMapper;
+import com.nokia.tsl_data.dao.WorkFlowDao;
 import com.nokia.tsl_data.service.TaskService;
+import com.nokia.tsl_data.service.UserCountService;
 import com.nokia.tsl_data.util.TextUtil;
 
 @SpringBootTest
@@ -17,26 +18,29 @@ class TslDataApplicationTest {
 
     @Test
     void test() {
-        taskService.generateReportV3("20240203");
+        taskService.generateReportV3("20240312");
     }
 
     @Autowired
-    private TargetTsRatioMapper targetTsRatioMapper;
+    private UserCountService userCountService;
 
     @Test
     void test2() {
-        String path = "/home/lfq/Documents/code/tsl-data/doc/数据订阅/客户提供/abc.txt";
-        List<String> lines = TextUtil.readLines(path);
+        String path = "D:/abc.txt";
+        List<String> lines = TextUtil.readLines(path, "utf-8");
         lines.forEach(line -> {
             String[] split = line.split("\t");
-            String city = split[0];
-            for (int i = 1; i < split.length; i++) {
-                String month = "2024" + (i >= 10 ? i : "0" + i);
-                double target = Double.parseDouble(split[i]);
-                System.out.println(city + "==" + month + "==" + target);
-                targetTsRatioMapper.updateServiceRequestTargetRatio(month, city, target);
-            }
+            System.out.println(split[0] + "==" + split[2]);
+            userCountService.updateManagementUserCount("202403", split[0], Double.parseDouble(split[2]));
         });
     }
 
+    @Autowired
+    private WorkFlowDao workFlowDao;
+
+    @Test
+    void test3() {
+        workFlowDao.selectTsDurationForDayV2("2024-03-13 00:00:00", "2024-03-13 13:00:00");
+    }
+
 }