package cn.gistack.sm.intelligentCall.service.impl; import cn.gistack.common.config.MyThreadPoolConfig; 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 cn.gistack.sm.sjztmd.entity.AttAdBase; import cn.gistack.sm.sjztmd.service.IAttAdBaseService; import cn.gistack.sm.sjztmd.vo.AttAdBaseVO; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; 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.jetbrains.annotations.NotNull; import org.springblade.core.redis.cache.BladeRedis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.stream.Collectors; @Slf4j @Service public class CallServiceImpl implements CallService { @Autowired private CallTaskMapper callTaskMapper; @Autowired private IAttAdBaseService attAdBaseService; @Autowired private RestTemplate restTemplate; @Autowired private BladeRedis bladeRedis; @Autowired private AsyncCallService asyncCallService; // @Value("${dial.task.url}") private String url = CallConstant.HOST; // @Value("${dial.task.empId}") private String empId = CallConstant.empId; // @Value("${dial.task.appId}") private String appId = CallConstant.AppKey; // @Value("${dial.task.appSecret}") private String appSecret = CallConstant.AppSecret; // @Value("${dial.task.scenesId}") private String scenesId = CallConstant.scenesId; // @Value("${dial.task.callingNumbers}") private String callingNumbers = CallConstant.callingNumbers; @Autowired private MyThreadPoolConfig myThreadPoolConfig; private static final String CONTENT_TYPE = "application/json; charset=UTF-8"; private static final String ACCEPT_TYPE = "application/json"; private static final String ACCEPT_ENCODING = "gzip"; private final static String CREATE_TASK_URL = "/api/task/createTask.json"; private final static String CALL_DETAIL_URL = "/api/task/callDetail.json"; /** * 创建任务 * @param map * @return */ @Override public List createTask(Map map) { List> params = (List>) map.get("list"); String requestUrl = url + CREATE_TASK_URL; LocalDateTime now = LocalDateTime.now(); String timestamp = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS")); String transId = generateTransId(now); String taskName = now.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH:mm:ss")) + "智能外呼";; if(null!= map.get("taskName") && !map.get("taskName").equals("")){ taskName = map.get("taskName").toString(); } String[] numbers = StringUtils.split(callingNumbers,","); String taskScheduleTime = LocalDateTime.now().plusHours(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); if (null!=map.get("taskScheduleTime") && !map.get("taskScheduleTime").equals("")){ taskScheduleTime = map.get("taskScheduleTime").toString(); } String scenesIds = scenesId; if (null!=map.get("scenesId") && !map.get("scenesId").equals("")){ scenesIds = map.get("scenesId").toString(); } JSONArray arr = getCalleeInfo(params); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add("Content-Type", CONTENT_TYPE); httpHeaders.add("Accept", ACCEPT_TYPE); httpHeaders.add("Accept-Encoding", ACCEPT_ENCODING); JSONObject paramJson = new JSONObject(); paramJson.put("taskName", taskName); paramJson.put("scenesId", scenesIds); paramJson.put("callingNumbers", numbers); paramJson.put("taskScheduleTime", taskScheduleTime); paramJson.put("calleeData", arr); paramJson.put("empId", empId); String token = getToken(appId, timestamp, transId, appSecret, paramJson.toJSONString()); JSONObject headerJson = new JSONObject(); headerJson.put("appId", appId); headerJson.put("timestamp", timestamp); headerJson.put("transId", transId); headerJson.put("token", token); JSONObject bodyJson = new JSONObject(); bodyJson.put("head", headerJson); bodyJson.put("body", paramJson); HttpEntity stringHttpEntity = new HttpEntity<>(bodyJson.toJSONString(), httpHeaders); log.info("创建超汛限智能外呼任务请求参数:{}", bodyJson.toJSONString()); ResponseEntity response = restTemplate.postForEntity(requestUrl, stringHttpEntity, String.class); log.info("创建外呼任务请求结果:{}", response.getBody()); if (response.getStatusCode() != HttpStatus.OK) { log.error("创建智能外呼任务失败:{}", response.getStatusCode()); } JSONObject jsonObject = JSON.parseObject(response.getBody()); Boolean success = jsonObject.getBoolean("success"); String taskId = ""; if (success){ //通过任务名称查询taskId taskId = callTaskMapper.getTaskIdByTaskName(taskName); } List list = new ArrayList<>(); list.add(response.getBody()); list.add(taskId); list.add(success.toString()); // 返回 return list; } /** * 获取通话详情 * @param taskId * @param calleeNumber * @return */ @Override public Object getCallDetail(String taskId, String calleeNumber) { String requestUrl = url + CALL_DETAIL_URL; LocalDateTime now = LocalDateTime.now(); String timestamp = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS")); String transId = generateTransId(now); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add("Content-Type", CONTENT_TYPE); httpHeaders.add("Accept", ACCEPT_TYPE); httpHeaders.add("Accept-Encoding", ACCEPT_ENCODING); JSONObject paramJson = new JSONObject(); paramJson.put("taskId", taskId); paramJson.put("calleeNumber", calleeNumber); JSONObject bodyJson = new JSONObject(); bodyJson.put("head", getHeadJson(appId, timestamp, transId, appSecret, paramJson.toJSONString())); bodyJson.put("body", paramJson); HttpEntity stringHttpEntity = new HttpEntity<>(bodyJson.toJSONString(), httpHeaders); ResponseEntity response = restTemplate.postForEntity(requestUrl, stringHttpEntity, String.class); log.info(response.toString()); if (response.getStatusCode() == HttpStatus.OK) { JSONObject responseJson = (JSONObject) JSONObject.parse(response.getBody()); assert responseJson != null; // return JSONObject.parseObject(responseJson.getString("data"), CallBackDetailVO.class); return response.getBody(); } return null; } private String getToken(String appId, String timestamp, String transId, String appSecret, String body) { String sb = "appId" + appId + "timestamp" + timestamp + "transId" + transId + body + appSecret; return DigestUtils.md5DigestAsHex(sb.getBytes()); } private JSONObject getHeadJson(String appId, String timestamp, String transId, String appSecret, String body) { String token = getToken(appId, timestamp, transId, appSecret, body); JSONObject headerJson = new JSONObject(); headerJson.put("appId", appId); headerJson.put("timestamp", timestamp); headerJson.put("transId", transId); headerJson.put("token", token); return headerJson; } private String generateTransId(LocalDateTime now) { String s = "000000" + RandomUtils.nextLong(0, 999999); String randomStr = StringUtils.substring(s, -6); return now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")) + randomStr; } /** * 封装被呼人对象 * @param params 被呼人信息 * @return 被呼人数组 */ private JSONArray getCalleeInfo(List> params) { JSONArray arr = new JSONArray(); params.forEach(map -> { String phone = map.get("phone"); String name = map.get("name"); String code = map.get("code"); String userName = map.get("userName"); String userId = map.get("userId"); String over = map.get("over"); if (StringUtils.isNotEmpty(phone) && StringUtils.isNotEmpty(name)) { JSONObject json = new JSONObject(); json.put("被叫号码", phone); json.put("水库名称", name); json.put("水库编码", code); json.put("用户名", userName); json.put("用户id", userId); json.put("超汛限多少米", over); arr.add(json); } }); return arr; } /** * 查詢任务列表数据 * @param page * @param callTask * @return */ @Override public IPage getCallListPage(IPage page, CallTaskStatistic callTask) { return page.setRecords(callTaskMapper.getCallListPage(page,callTask)); } /** * 查询呼叫详情列表信息 * @param callTaskResult * @param page * @return */ @Override public IPage getCallTaskResultListPage(IPage page, CallTaskResultVO callTaskResult) { List list = new ArrayList<>(); if (null!= callTaskResult.getAreaName() && !callTaskResult.getAreaName().equals("")){ // 查询所有下级区域code list = getAllChildrenAreaByAreaCode(callTaskResult.getAreaName()); } List resultListPage = callTaskMapper.getCallTaskResultListPage(page, callTaskResult,list,null); return page.setRecords(resultListPage); } /** * 导出呼叫详情列表信息 * @param callTaskResult * @return */ @Override public Object getCallTaskResultList(CallTaskResultVO callTaskResult) { List list = new ArrayList<>(); List idsList = new ArrayList<>(); if (null!= callTaskResult.getAreaName() && !callTaskResult.getAreaName().equals("")){ // 查询所有下级区域code list = getAllChildrenAreaByAreaCode(callTaskResult.getAreaName()); } if (null!= callTaskResult.getIds() && !callTaskResult.getIds().equals("")){ // 查询所有下级区域code idsList = Arrays.asList(callTaskResult.getIds().split(",")); } List resultListPage = callTaskMapper.getCallTaskResultListPage(null, callTaskResult,list,idsList); // 返回 return resultListPage; } // /** // * 查询智能外呼统计数据-按日期-行政区统计 // * @param page // * @param callTaskStatistic // * @return // */ // @Override // public Object getOutgoingStatisticList(IPage page,CallTaskStatistic callTaskStatistic) { // if (null==callTaskStatistic.getCreateTime() || callTaskStatistic.getCreateTime().equals("")){ // long l = System.currentTimeMillis(); // // 设置当前时间的前一天 // callTaskStatistic.setCreateTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date(l - 60*60*24*1000))); // } // ThreadPoolExecutor executor = myThreadPoolConfig.threadPoolExecutor(); // // 异步查询统计数据 // CompletableFuture> callTaskStatisticCompletableFuture = getListCompletableFuture(page, callTaskStatistic, executor); // // 查询 按区域统计连续三天,连续两天未接通,前一天拒接对应的数量 // Map threeDay = computationTime(callTaskStatistic.getCreateTime(), 2); // Map twoDay = computationTime(callTaskStatistic.getCreateTime(), 1); // Map oneDay = computationTime(callTaskStatistic.getCreateTime(), 0); // // 查询 // CompletableFuture> threeDayNotCallConnect = getListCompletableFuture(callTaskStatistic, executor, threeDay, "200003", 2); // CompletableFuture> twoDayNotCallConnect = getListCompletableFuture(callTaskStatistic, executor, twoDay, "200003", 1); // CompletableFuture> oneDayNotCallConnect = getListCompletableFuture(callTaskStatistic, executor, oneDay, "200005", 0); // //等待所有任务执行完成 // try { // CompletableFuture.allOf(callTaskStatisticCompletableFuture,threeDayNotCallConnect,twoDayNotCallConnect,oneDayNotCallConnect).get(); // // 数据处理 // List callTaskStatistics = getCallTaskStatistics(callTaskStatisticCompletableFuture, oneDay, threeDayNotCallConnect, twoDayNotCallConnect, oneDayNotCallConnect); // // 取当前行政区总数据 // List totalList = getTotalCallTaskStatistics(callTaskStatistics,callTaskStatistic); // // 排序 // callTaskStatistics = getCallTaskStatisticsByOrder(callTaskStatistic, callTaskStatistics); // // 合并数据 // totalList.addAll(callTaskStatistics); // // 返回数据 // if (null!= callTaskStatistic.getIsPage()) { // return totalList; // }else { // return page.setRecords(totalList); // } // } catch (InterruptedException e) { // e.printStackTrace(); // } catch (ExecutionException e) { // e.printStackTrace(); // } // // 返回 // return null; // } /** * 查询智能外呼统计数据-按日期-行政区统计 * @param page * @param callTaskStatistic * @return */ @Override public Object getOutgoingStatisticList(IPage page,CallTaskStatistic callTaskStatistic) { if (null==callTaskStatistic.getCreateTime() || callTaskStatistic.getCreateTime().equals("")){ long l = System.currentTimeMillis(); // 设置当前时间的前一天 callTaskStatistic.setCreateTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date(l - 60*60*24*1000))); } ThreadPoolExecutor executor = myThreadPoolConfig.threadPoolExecutor(); // 异步查询当前天日常呼叫(3次)统计数据 CompletableFuture> callTaskStatisticCompletableFuture = getListCompletableFuture(page, callTaskStatistic, executor); // 查询当前天除去日常呼叫外的统计数据 CompletableFuture> notCallConnect = getListCompletableFuture(callTaskStatistic,executor); //等待所有任务执行完成 try { CompletableFuture.allOf(callTaskStatisticCompletableFuture,notCallConnect).get(); // 数据处理 List callTaskStatistics = getCallTaskStatistics(callTaskStatisticCompletableFuture,null,null,null, notCallConnect,callTaskStatistic); // 取当前行政区总数据 List totalList = getTotalCallTaskStatistics(callTaskStatistics,callTaskStatistic); // 排序 callTaskStatistics = getCallTaskStatisticsByOrder(callTaskStatistic, callTaskStatistics); // 合并数据 totalList.addAll(callTaskStatistics); // 返回数据 if (null!= callTaskStatistic.getIsPage()) { return totalList; }else { return page.setRecords(totalList); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } // 返回 return null; } /** * 获取当前行政区总数据 * @param callTaskStatistics * @param callTaskStatisticEntity * @return */ private List getTotalCallTaskStatistics(List callTaskStatistics,CallTaskStatistic callTaskStatisticEntity) { List statistics = new ArrayList<>(); CallTaskStatistic callTaskStatistic = new CallTaskStatistic(); Integer totalCalleeNumberCount = 0; Integer totalConnectionCount = 0; Integer totalThreeNoConnectCount = 0; Integer totalTwoNoConnectCount = 0; Integer totalRefuseConnectCount = 0; // 遍历 for (CallTaskStatistic taskStatistic : callTaskStatistics) { totalCalleeNumberCount += Integer.parseInt(taskStatistic.getCalleeNumberCount()); totalConnectionCount += Integer.parseInt(taskStatistic.getConnectionCount()); totalThreeNoConnectCount += taskStatistic.getThreeNoConnectCount(); totalTwoNoConnectCount += taskStatistic.getTwoNoConnectCount(); totalRefuseConnectCount += taskStatistic.getRefuseConnectCount(); } // 设置数据 callTaskStatistic.setCalleeNumberCount(totalCalleeNumberCount.toString()); callTaskStatistic.setConnectionCount(totalConnectionCount.toString()); callTaskStatistic.setThreeNoConnectCount(totalThreeNoConnectCount); callTaskStatistic.setTwoNoConnectCount(totalTwoNoConnectCount); callTaskStatistic.setRefuseConnectCount(totalRefuseConnectCount); callTaskStatistic.setCreateTime(callTaskStatistics.get(0).getCreateTime()); // 查询当前行政区名称 AttAdBase attAdBase = new AttAdBase(); attAdBase.setGuid(callTaskStatisticEntity.getAdCode()); AttAdBaseVO detail = attAdBaseService.getDetail(attAdBase); callTaskStatistic.setAdCode(callTaskStatisticEntity.getAdCode()); if (null != detail){ callTaskStatistic.setAdName(detail.getAdName()); } // 计算比例 //格式化小数 DecimalFormat df = new DecimalFormat("0.00"); callTaskStatistic.setCallCompletingRate(df.format((float)totalConnectionCount/totalCalleeNumberCount*100)); statistics.add(callTaskStatistic); // 返回 return statistics; } /** * 排序 * @param callTaskStatistic * @param callTaskStatistics * @return */ private List getCallTaskStatisticsByOrder(CallTaskStatistic callTaskStatistic, List callTaskStatistics) { // 排序 if (null != callTaskStatistic.getSortName() && !callTaskStatistic.getSortName().equals("")) { if (callTaskStatistic.getSortName().equals("refuseConnectCount")) { if (callTaskStatistic.getSortOrder().equals("desc")) { callTaskStatistics = callTaskStatistics.stream().sorted(Comparator.comparing(CallTaskStatistic::getRefuseConnectCount).reversed()).collect(Collectors.toList()); }else { callTaskStatistics = callTaskStatistics.stream().sorted(Comparator.comparing(CallTaskStatistic::getRefuseConnectCount)).collect(Collectors.toList()); } } if (callTaskStatistic.getSortName().equals("twoNoConnectCount")) { if (callTaskStatistic.getSortOrder().equals("desc")) { callTaskStatistics = callTaskStatistics.stream().sorted(Comparator.comparing(CallTaskStatistic::getTwoNoConnectCount).reversed()).collect(Collectors.toList()); }else { callTaskStatistics = callTaskStatistics.stream().sorted(Comparator.comparing(CallTaskStatistic::getTwoNoConnectCount)).collect(Collectors.toList()); } } if (callTaskStatistic.getSortName().equals("threeNoConnectCount")) { if (callTaskStatistic.getSortOrder().equals("desc")) { callTaskStatistics = callTaskStatistics.stream().sorted(Comparator.comparing(CallTaskStatistic::getThreeNoConnectCount).reversed()).collect(Collectors.toList()); }else { callTaskStatistics = callTaskStatistics.stream().sorted(Comparator.comparing(CallTaskStatistic::getThreeNoConnectCount)).collect(Collectors.toList()); } } } return callTaskStatistics; } /** * 查询当前天除去日常呼叫外的统计数据 * @param callTaskStatistic * @param executor * @return */ @NotNull private CompletableFuture> getListCompletableFuture(CallTaskStatistic callTaskStatistic, ThreadPoolExecutor executor) { return CompletableFuture.supplyAsync(()->{ List outgoingStatisticList = callTaskMapper.getNoDayOutgoingStatisticList(callTaskStatistic); return outgoingStatisticList; },executor); } /** * 按行政区查询对应的接通率 * @param page * @param callTaskStatistic * @param executor * @return */ @NotNull private CompletableFuture> getListCompletableFuture(IPage page, CallTaskStatistic callTaskStatistic, ThreadPoolExecutor executor) { return CompletableFuture.supplyAsync(()->{ List outgoingStatisticList = new ArrayList<>(); // 判断是否分页 if (null!= callTaskStatistic.getIsPage()){ // 不分页 outgoingStatisticList = callTaskMapper.getOutgoingStatisticList(null,callTaskStatistic,null); }else { // 按天查询数据 outgoingStatisticList = callTaskMapper.getOutgoingStatisticList(page, callTaskStatistic, null); } return outgoingStatisticList; },executor); } /** * 数据处理 * @param callTaskStatisticCompletableFuture * @param oneDay * @param threeDayNotCallConnect * @param twoDayNotCallConnect * @param oneDayNotCallConnect * @return * @throws InterruptedException * @throws ExecutionException */ @NotNull private List getCallTaskStatistics(CompletableFuture> callTaskStatisticCompletableFuture, Map oneDay, CompletableFuture> threeDayNotCallConnect, CompletableFuture> twoDayNotCallConnect, CompletableFuture> oneDayNotCallConnect, CallTaskStatistic callTaskStatistic) throws InterruptedException, ExecutionException { // 获取信息 List callTaskStatistics = callTaskStatisticCompletableFuture.get(); // List threeNotConnectTaskStatisticsList = threeDayNotCallConnect.get(); // List twoNotConnectTaskStatisticsList = twoDayNotCallConnect.get(); List oneNotConnectTaskStatisticsList = oneDayNotCallConnect.get(); // 遍历 for (CallTaskStatistic taskStatistic : callTaskStatistics) { // taskStatistic.setCreateTime(oneDay.get("endTime").toString()); taskStatistic.setCreateTime(callTaskStatistic.getCreateTime()); // for (CallTaskStatistic statistic : threeNotConnectTaskStatisticsList) { // if (taskStatistic.getGuid().equals(statistic.getGuid())){ // taskStatistic.setThreeNoConnectCount(statistic.getCount()); // } // } // for (CallTaskStatistic statistic : twoNotConnectTaskStatisticsList) { // if (taskStatistic.getGuid().equals(statistic.getGuid())){ // taskStatistic.setTwoNoConnectCount(statistic.getCount()); // } // } for (CallTaskStatistic statistic : oneNotConnectTaskStatisticsList) { if (taskStatistic.getGuid().equals(statistic.getGuid())){ Integer count = Integer.parseInt(taskStatistic.getCalleeNumberCount()) + Integer.parseInt(statistic.getCalleeNumberCount()); Integer connectCount = Integer.parseInt(taskStatistic.getConnectionCount()) + Integer.parseInt(statistic.getConnectionCount()); taskStatistic.setCalleeNumberCount(count.toString()); taskStatistic.setConnectionCount(connectCount.toString()); taskStatistic.setRefuseConnectCount(taskStatistic.getRefuseConnectCount() + statistic.getRefuseConnectCount()); // 计算比例 if (connectCount==0){ taskStatistic.setCallCompletingRate("0"); }else { //格式化小数 DecimalFormat df = new DecimalFormat("0.00"); taskStatistic.setCallCompletingRate(df.format((float) connectCount / count * 100)); } } } } return callTaskStatistics; } /** * 按行政区查询未接通/拒接统计数据 * @param callTaskStatistic * @param executor * @param threeDay 日期 * @param s 状态 * @param i 数量 * @return */ @NotNull private CompletableFuture> getListCompletableFuture(CallTaskStatistic callTaskStatistic, ThreadPoolExecutor executor, Map threeDay, String s, int i) { return CompletableFuture.supplyAsync(() -> { // 按天查询数据,区域统计 List threeDayNotCallConnectStatisticList = callTaskMapper.getNotCallConnectStatisticList(callTaskStatistic, s, i, threeDay); return threeDayNotCallConnectStatisticList; }, executor); } /** * 查询智能外呼统计数据-行政区统计 * @param callTaskStatistic * @return */ @Override public Object getOutgoingStatisticByArea(CallTaskStatistic callTaskStatistic) { return callTaskMapper.getOutgoingStatisticByArea(callTaskStatistic); } /** * 查询所有下级区域 * @param areaCode * @return */ private List getAllChildrenAreaByAreaCode(String areaCode) { return callTaskMapper.getAllChildrenAreaByAreaCode(areaCode); } /** * 通过水库编码获取行政区名称 * @param adCode * @return */ private String getAreaNameByAdCode(String adCode) { // 通过adCode查询区域名称 return callTaskMapper.getAreaNameByAdCode(adCode); } /** * 通过行政区编号获取水库名称 * @param areaCode * @return */ private List getWaterNameByAreaCode(String areaCode) { // 通过行政区编号获取水库名称 return callTaskMapper.getWaterNameByAreaCode(areaCode); } /** * 根据条件自动创建外呼任务 * @param params * @return */ @Override public List createCallTaskByParam(Map params) { // 常规任务,每天上午11点打150人,下午2点打11点未接人员,下午5点打下午2点未接通人员 String redisOneKey = bladeRedis.get(CallConstant.call_task_key); if (null==redisOneKey){ List stringList = everydayCall(params); // 取出数据进行设置 taskId bladeRedis.setEx(CallConstant.call_task_key,stringList.get(1)+","+1,6*60*60L); // 异步保存日常关联呼叫任务信息 asyncCallService.saveDailyCallTask(stringList.get(1),1); // 响应 return stringList; }else { return createEverydayAfter(redisOneKey); } } /** * 日常外呼任务未接通的继续拨打 * @param redisOneKey 取值为上一次外呼的任务id * @return */ private List createEverydayAfter(String redisOneKey) { // redisOneKey = "2216,1"; String[] split = redisOneKey.split(","); String taskId = split[0]; String type = split[1]; List stringList = new ArrayList<>(); Map params = new HashMap<>(); // 通过 taskId 查询未呼叫人员(mysql) List list = callTaskMapper.getCallNotConnectListByTaskId(taskId); if (list.size()>0){ Set scenes = new HashSet<>(list); // 传入调度时间和随机得到的人员信息进行任务的创建并返回 params.put("list",setForListMap(scenes)); // 调度时间处理 params.put("taskScheduleTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); // 创建任务 stringList = createTask(params); // 判断是否发送短信 if (type.equals("1")){ // 取出数据进行设置 taskId bladeRedis.setEx(CallConstant.call_task_key,stringList.get(1)+","+2,6*60*60L); // 异步保存日常关联呼叫任务信息 asyncCallService.saveDailyCallTask(stringList.get(1),2); } // 判断是否发送短信 if (type.equals("2")){ // 新增一个参数代表需要发短信 stringList.add("3"); // 异步保存日常关联呼叫任务信息 asyncCallService.saveDailyCallTask(stringList.get(1),3); } } // 返回 return stringList; } /** * 日常外呼任务创建 * @param params * @return */ private List everydayCall(Map params) { // 自动创建任务的 4个条件 1:呼叫人数 2:调度时间 3:是否超汛限 4:多少天内呼叫过的不呼叫(天数) //1. 调用中台接口查询出所有需要发任务的水库巡查责任人相关信息(该处需要将是否超汛限条件传入) JSONArray jsonArray = getZtWaterMangerData(params); // 过滤得到手机号集合(排查手机号为null的数据) List totalList = filterJsonToList(jsonArray); //2. 查询外呼多少天内已呼叫过的人员手机号集合信息 // 计算开始时间,结束时间 computationTime(params); // 查询对应数据 List list = callTaskMapper.getCallUserPhoneByParam(params); //3. 比对中台得到的数据和外呼已呼叫信息,从中随机取出呼叫人数的信息 Set 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"); // 创建任务并返回结果 return createTask(params); } /** * 智能外呼呼叫前一天未接通人员 * @param map 包含调度时间 * @return */ @Override public List createOutCallTaskByNotConnectJobHandler(Map map) { map.put("day",1); map.put("isOver",""); // 自动创建任务的 条件1:昨天外呼未接通人员 条件2:前三天如果同一个人都未接通,则不再呼叫 // 计算开始时间,结束时间 computationTime(map); // 1. 查询前一天呼叫未接通人员 List oneDayCallNotConnectList = callTaskMapper.getBeforeOneDayCallNotConnect(map); if (oneDayCallNotConnectList.size()>0) { // 2. 判断是否填报,查询前一天已填报的人员 List fillRecordList = callTaskMapper.getFillRecordList(map); // 3. 查询三天都未接通的人员 map.put("day", 3); List threeDayCallNotConnectList = callTaskMapper.getBeforeThreeDayCallNotConnect(map); // 4. 组装数据,从前一天呼叫未接通里面去除已填报人员,去除连续三天未接人员 Set taskRandomList = callNotConnectListDataHandle(oneDayCallNotConnectList, fillRecordList, threeDayCallNotConnectList); // 5. 传入调度时间和随机得到的人员信息进行任务的创建并返回 map.put("list", setForListMap(taskRandomList)); // 调度时间处理 map.put("taskScheduleTime", new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " " + map.get("taskScheduleTime") + ":00"); // 创建任务并返回结果 return createTask(map); } return null; } /** * 组装数据,从前一天呼叫未接通里面去除已填报人员,去除连续三天未接人员 * @param oneDayCallNotConnectList 前一天呼叫未接通人员信息 * @param fillRecordList 前一天已填报的人员手机号集合 * @param threeDayCallNotConnectList 连续三天都未接通的人员手机号集合 * @return */ private Set callNotConnectListDataHandle(List oneDayCallNotConnectList, List fillRecordList, List threeDayCallNotConnectList) { // 取差集 // 去除前一天已填报的人员手机号集合 List sceneList = oneDayCallNotConnectList.stream().filter(item -> !fillRecordList.contains(item.getPhone())).collect(Collectors.toList()); // 再去除连续三天都未接通的人员手机号集合 List resultList = sceneList.stream().filter(item -> !threeDayCallNotConnectList.contains(item.getPhone())).collect(Collectors.toList()); // 转set去重 HashSet scenes = new HashSet<>(resultList); // 返回 return scenes; } /** * hashSet 转 List> * @param taskRandomList * @return */ private List> setForListMap(Set taskRandomList) { List> list = new ArrayList<>(); for (Scene scene : taskRandomList) { Map 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 getCreateTaskRandomList(Map params, List totalList, List list) { Integer personNumber = ZtConstant.person_number; if (!params.get("personNumber").equals("")){ personNumber = Integer.parseInt(params.get("personNumber").toString()); } // 先取差集 List sceneList = totalList.stream().filter(item -> !list.contains(item.getPhone())).collect(Collectors.toList()); // 如果差集数量不够 预定的数量(超汛情况),则从未超汛情况数据中补齐预定的数量 if (sceneList.size() map = new HashMap<>(); map.put("isOver",0); // 查询未超汛的数据 JSONArray jsonArray = getZtWaterMangerData(map); // 过滤得到手机号集合(排查手机号为null的数据) List sceneListNoOver = filterJsonToList(jsonArray); // 取差集 List differenceSceneListNoOver = sceneListNoOver.stream().filter(item -> !list.contains(item.getPhone())).collect(Collectors.toList()); // 再随机抽取对应人员手机号 Set hashSet = new HashSet<>(); // 先将超汛的加入集合 for (Scene scene : sceneList) { hashSet.add(scene); } // 未超汛的补充 personNumber = personNumber - sceneList.size(); Random random = new Random(); for (int i = 0; i < differenceSceneListNoOver.size(); i++) { // 获取随机数作为下标索引 int num = random.nextInt(differenceSceneListNoOver.size()); // 保存到 hashSet ,保证唯一 hashSet.add(differenceSceneListNoOver.get(num)); // 数量达到预期设定退出循环 if (hashSet.size() == personNumber) { break; } } return hashSet; }else { // 再随机抽取对应人员手机号 Set 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 filterJsonToList(JSONArray jsonArray) { List 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 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 time 传入的时间 * @param day 天数 */ private Map computationTime(String time,Integer day) { HashMap map = new HashMap<>(2); long l = 0; try { l = new SimpleDateFormat("yyyy-MM-dd").parse(time).getTime(); } catch (ParseException e) { e.printStackTrace(); } 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)); // 加入到参数中 map.put("startTime",startTime); map.put("endTime",endTime); // 返回 return map; } /** * 调用中台接口查询出所有需要发任务的水库巡查责任人相关信息(该处需要将是否超汛限条件传入) * @param params * @return */ private JSONArray getZtWaterMangerData(Map params) { //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.add(ZtConstant.header_key, ZtConstant.header_value); //封装请求头 HttpEntity> formEntity = new HttpEntity>(headers); try { //有请求头,有参数请求 ResponseEntity 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; } /** * 查询未接通,拒接的呼叫结果详情列表信息 * @param page * @param callTaskStatistic * @return */ @Override public Object getCallNotConnectResultList(IPage page,CallTaskStatistic callTaskStatistic) { // 计算时间 Map map = computationTime(callTaskStatistic.getCreateTime(), callTaskStatistic.getCount()); List list = new ArrayList<>(); if (null!= callTaskStatistic.getAdCode() && !callTaskStatistic.getAdCode().equals("")){ // 查询所有下级区域code list = getAllChildrenAreaByAreaCode(callTaskStatistic.getAdCode()); } if (null!=callTaskStatistic.getIsPage()){ // 不分页 return callTaskMapper.getCallNotConnectResultList(null, list,callTaskStatistic,map); } List callNotConnectResultList = callTaskMapper.getCallNotConnectResultList(page,list, callTaskStatistic,map); // 返回 return page.setRecords(callNotConnectResultList); } /** * 按日期行政区呼叫结果详情列表信息 * @param callTaskStatistic * @param page * @return */ @Override public Object getCallResultList(IPage page, CallTaskStatistic callTaskStatistic) { List list = new ArrayList<>(); if (null!= callTaskStatistic.getAdCode() && !callTaskStatistic.getAdCode().equals("")){ // 查询所有下级区域code list = getAllChildrenAreaByAreaCode(callTaskStatistic.getAdCode()); } if (null!=callTaskStatistic.getIsPage()){ // 不分页 return callTaskMapper.getCallResultList(null, list,callTaskStatistic); } List callNotConnectResultList = callTaskMapper.getCallResultList(page,list, callTaskStatistic); // 返回 return page.setRecords(callNotConnectResultList); } }