zhongrj
2023-05-19 ecb72d0ff3aa06c53502821eff7412bf16130ae3
自能外呼自动创建任务接口新增
5 files modified
2 files added
280 ■■■■■ changed files
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/constant/ZtConstant.java 35 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/controller/CallController.java 11 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/entity/Scene.java 41 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/mapper/CallTaskMapper.java 8 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/mapper/CallTaskMapper.xml 7 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/service/CallService.java 7 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/service/impl/CallServiceImpl.java 171 ●●●●● patch | view | raw | blame | history
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/constant/ZtConstant.java
New file
@@ -0,0 +1,35 @@
package cn.gistack.sm.intelligentCall.constant;
/**
 * 中台接口请求信息常量
 * @author zhongrj
 * @since 2023-04-21
 */
public class ZtConstant {
    /**
     * 查询水库对应超汛巡查信息url
     */
    public static final String patr_person_api = "http://10.10.2.192/services/1234567890ABCDEFGHIJKLMN/over_z_last/patr_person/api";
    /**
     * 请求头 key
     */
    public static final String header_key = "apiKey";
    /**
     * 请求头 value
     */
    public static final String header_value = "F1DBECD719108635189480CF60E6553ADB3109616426BD537F25A430DFC613B491A025C4A51E77FD08C6E5B7CBE05917A461286E7B6D69F1AB1B14F946149D2065B0C675F8FEDF4B9B05C1496881BC5A";
    /**
     * 默认发送呼叫人数
     */
    public static final Integer person_number = 20;
    /**
     * 默认不呼叫人员的天数
     */
    public static final Integer day_number =  10;
}
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/controller/CallController.java
@@ -1,6 +1,7 @@
package cn.gistack.sm.intelligentCall.controller;
import cn.gistack.sm.intelligentCall.entity.CallTaskResult;
import cn.gistack.sm.intelligentCall.entity.Scene;
import cn.gistack.sm.intelligentCall.service.CallService;
import cn.gistack.sm.intelligentCall.vo.CallTaskResultVO;
import cn.gistack.sm.intelligentCall.vo.CallTaskStatistic;
@@ -108,4 +109,14 @@
        return R.data(callService.getOutgoingStatisticByArea(callTaskStatistic));
    }
    /**
     * 根据条件自动创建外呼任务
     * @param params
     * @return
     */
    @PostMapping("/createCallTaskByParams")
    public R createCallTaskByParam(@RequestBody Map<String, Object> params){
        // 返回
        return R.status(callService.createCallTaskByParam(params));
    }
}
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/entity/Scene.java
New file
@@ -0,0 +1,41 @@
package cn.gistack.sm.intelligentCall.entity;
import lombok.Data;
import java.io.Serializable;
/**
 * 超汛场景参数实体
 * @author zhongrj
 * @date 2023-05-19
 */
@Data
public class Scene implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 巡查责任人姓名
     */
    private String username;
    /**
     * 巡查责任人联系方式
     */
    private String phone;
    /**
     * 水库名称
     */
    private String waterName;
    /**
     * 水库编号
     */
    private String waterCode;
    /**
     * 用户id
     */
    private String userId;
}
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/mapper/CallTaskMapper.java
@@ -9,6 +9,7 @@
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * @author zhongrj
@@ -81,4 +82,11 @@
     */
    @DS("zt")
    List<CallTaskStatistic> getOutgoingStatisticByArea(@Param("callTaskStatistic") CallTaskStatistic callTaskStatistic);
    /**
     * 查询外呼多少天内已呼叫过的人员手机号集合信息
     * @param params
     * @return
     */
    List<String> getCallUserPhoneByParam(@Param("params")Map<String, Object> params);
}
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/mapper/CallTaskMapper.xml
@@ -284,4 +284,11 @@
            order by aab."guid"
        ) b
    </select>
    <!--查询外呼多少天内已呼叫过的人员手机号集合信息-->
    <select id="getCallUserPhoneByParam" resultType="java.lang.String">
        select "callee_number" from SJZT_ODS."call_task_result"
        where date_format("gmt_create",'%Y-%m-%d') >= #{params.startTime}
        and date_format("gmt_create",'%Y-%m-%d') &lt;= #{params.endTime}
    </select>
</mapper>
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/service/CallService.java
@@ -61,4 +61,11 @@
     * @return
     */
    Object getOutgoingStatisticByArea(CallTaskStatistic callTaskStatistic);
    /**
     * 根据条件自动创建外呼任务
     * @param params
     * @return
     */
    boolean createCallTaskByParam(Map<String, Object> params);
}
skjcmanager/skjcmanager-service/skjcmanager-sm/src/main/java/cn/gistack/sm/intelligentCall/service/impl/CallServiceImpl.java
@@ -1,31 +1,32 @@
package cn.gistack.sm.intelligentCall.service.impl;
import cn.gistack.sm.intelligentCall.constant.CallConstant;
import cn.gistack.sm.intelligentCall.constant.ZtConstant;
import cn.gistack.sm.intelligentCall.entity.Scene;
import cn.gistack.sm.intelligentCall.mapper.CallTaskMapper;
import cn.gistack.sm.intelligentCall.service.CallService;
import cn.gistack.sm.intelligentCall.vo.CallTaskResultVO;
import cn.gistack.sm.intelligentCall.vo.CallTaskStatistic;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@@ -312,4 +313,156 @@
        // 通过行政区编号获取水库名称
        return callTaskMapper.getWaterNameByAreaCode(areaCode);
    }
    /**
     * 根据条件自动创建外呼任务
     * @param params
     * @return
     */
    @Override
    public boolean createCallTaskByParam(Map<String, Object> params) {
        // 自动创建任务的 4个条件  1:呼叫人数  2:调度时间  3:是否超汛限  4:多少天内呼叫过的不呼叫(天数)
        //1. 调用中台接口查询出所有需要发任务的水库巡查责任人相关信息(该处需要将是否超汛限条件传入)
        JSONArray jsonArray = getZtWaterMangerData(params);
        // 过滤得到手机号集合(排查手机号为null的数据)
        List<Scene> totalList = filterJsonToList(jsonArray);
        //2. 查询外呼多少天内已呼叫过的人员手机号集合信息
        // 计算开始时间,结束时间
        computationTime(params);
        // 查询对应数据
        List<String> list = callTaskMapper.getCallUserPhoneByParam(params);
        //3. 比对中台得到的数据和外呼已呼叫信息,从中随机取出呼叫人数的信息
        Set<Scene> taskRandomList = getCreateTaskRandomList(params, totalList, list);
        //4. 传入调度时间和随机得到的人员信息进行任务的创建并返回
        params.put("list",setForListMap(taskRandomList));
        // 调度时间处理
        params.put("taskScheduleTime",new SimpleDateFormat("yyyy-MM-dd").format(new Date())+ " " +params.get("taskScheduleTime") + ":00");
        // 创建任务
        createTask(params);
        //5. 返回
        return true;
    }
    /**
     * hashSet 转 List<Map<String,String>>
     * @param taskRandomList
     * @return
     */
    private List<Map<String,String>> setForListMap(Set<Scene> taskRandomList) {
        List<Map<String,String>> list = new ArrayList<>();
        for (Scene scene : taskRandomList) {
            Map<String, String> map = new HashMap<>();
            map.put("phone",scene.getPhone());
            map.put("name",scene.getWaterName());
            map.put("code",scene.getWaterCode());
            map.put("userName",scene.getUsername());
            map.put("userId",scene.getPhone());
            map.put("over","");
            // 加入集合
            list.add(map);
        }
        return list;
    }
    /**
     * 获取随机呼叫的相关信息
     * @param params
     * @param totalList
     * @param list
     */
    private Set<Scene> getCreateTaskRandomList(Map<String, Object> params, List<Scene> totalList, List<String> list) {
        Integer personNumber = ZtConstant.person_number;
        if (!params.get("personNumber").equals("")){
            personNumber = Integer.parseInt(params.get("personNumber").toString());
        }
        // 先取差集
        List<Scene> sceneList = totalList.stream().filter(item -> !list.contains(item.getPhone())).collect(Collectors.toList());
        // 再随机抽取对应人员手机号
        Set<Scene> hashSet = new HashSet<>();
        Random random =new Random();
        for(int i=0;i<sceneList.size();i++){
            // 获取随机数作为下标索引
            int num = random.nextInt(sceneList.size());
            // 保存到 hashSet ,保证唯一
            hashSet.add(sceneList.get(num));
            // 数量达到预期设定退出循环
            if (hashSet.size()==personNumber){
                break;
            }
        }
        return hashSet;
    }
    /**
     * 将 jsonArray 取出手机号得到新的集合
     * @param jsonArray
     * @return
     */
    private List<Scene> filterJsonToList(JSONArray jsonArray) {
        List<Scene> list = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            if (null != jsonArray.getJSONObject(i).get("user_phone") &&
                !jsonArray.getJSONObject(i).get("user_phone").equals("")){
                Scene scene = new Scene();
                scene.setPhone(jsonArray.getJSONObject(i).get("user_phone").toString());
                scene.setUsername(jsonArray.getJSONObject(i).get("user_name").toString());
                scene.setUserId(jsonArray.getJSONObject(i).get("user_phone").toString());
                scene.setWaterName(jsonArray.getJSONObject(i).get("res_nm").toString());
                scene.setWaterCode(jsonArray.getJSONObject(i).get("res_cd").toString());
                // 加入集合
                list.add(scene);
            }
        }
        return list;
    }
    /**
     * 计算时间
     * @param params
     */
    private void computationTime(Map<String, Object> params) {
        long l = System.currentTimeMillis();
        Integer day = ZtConstant.day_number;
        // 获取天数
        if (null != params.get("day")){
            day = Integer.parseInt(params.get("day").toString());
        }
        long m = 60*60*24*1000*day;
        // 相减得到时间
        Long x = l-m;
        // 格式化日期
        String startTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(x));
        String endTime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(l));
        // 加入到参数中
        params.put("startTime",startTime);
        params.put("endTime",endTime);
    }
    /**
     * 调用中台接口查询出所有需要发任务的水库巡查责任人相关信息(该处需要将是否超汛限条件传入)
     * @param params
     * @return
     */
    private JSONArray getZtWaterMangerData(Map<String, Object> params) {
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add(ZtConstant.header_key, ZtConstant.header_value);
        //封装请求头
        HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<MultiValueMap<String, Object>>(headers);
        try {
            //有请求头,有参数请求
            ResponseEntity<String> responseEntity =
                restTemplate.exchange(ZtConstant.patr_person_api+"?is_over="+params.get("isOver"),
                    HttpMethod.GET,
                    formEntity,
                    String.class);
            JSONObject jsonObject = JSON.parseObject(responseEntity.getBody());
            JSONArray jsonArray = JSONArray.parseArray(jsonObject.get("resultList").toString());
            // 返回
            return jsonArray;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}