| | |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.*; |
| | | import com.smartor.common.FtpService; |
| | | import com.smartor.common.SendService; |
| | | import com.smartor.config.PhoneUtils; |
| | | import com.smartor.domain.*; |
| | | import com.smartor.mapper.*; |
| | |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.math.BigDecimal; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | |
| | | private IIvrTaskTemplateScriptService iIvrTaskTemplateScriptService; |
| | | |
| | | @Autowired |
| | | private IServiceOutPathService iServiceOutPathService; |
| | | |
| | | @Autowired |
| | | private FtpService ftpService; |
| | | |
| | | @Value("${pri_key}") |
| | | private String pri_key; |
| | | |
| | | @Value("${pub_key}") |
| | | private String pub_key; |
| | | |
| | | @Value("${ASRCallBackPath}") |
| | | private String ASRCallBackPath; |
| | | |
| | | @Autowired |
| | | private SendService sendService; |
| | | |
| | | @Value("${hangup}") |
| | | private String hangup; |
| | |
| | | @Value("${voicePathPrefix}") |
| | | private String voicePathPrefix; |
| | | |
| | | @Value("${localIP}") |
| | | private String localIP; |
| | | |
| | | @Value("${req_path}") |
| | | private String req_path; |
| | | |
| | | @Value("${xhsmsPath}") |
| | | private String xhsmsPath; |
| | | |
| | | /** |
| | | * 查询单一任务(随访) |
| | |
| | | if (noVoice == ivrTaskTemplateVO.getNoVoiceNum().intValue()) { |
| | | //已经问了对应的遍数,就判断是否还有下一题 |
| | | if (nowQuestion.getTargetid() == IvrTaskTemplateScriptVOs.size()) { |
| | | ServiceSubtask ss = new ServiceSubtask(); |
| | | ss.setId(serviceSubtask.getId()); |
| | | ss.setSendstate(5L); |
| | | ss.setRemark("电话无响应"); |
| | | serviceSubtaskMapper.updateServiceSubtask(ss); |
| | | //没有下一题了,就挂断电话,播放结束语 |
| | | redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES); |
| | | phoneUtils.ttsPlayback(ivrTaskTemplateVO.getRevisitAfter(), phoneCallBackVO.getUuid()); |
| | |
| | | return; |
| | | } else if (nextQuestion > IvrTaskTemplateScriptVOs.size()) { |
| | | //没有下一题了,就结束了 |
| | | ServiceSubtask ss = new ServiceSubtask(); |
| | | ss.setId(serviceSubtask.getId()); |
| | | ss.setSendstate(6L); |
| | | serviceSubtaskMapper.updateServiceSubtask(ss); |
| | | String date = simpleDateFormat1.format(new Date()); |
| | | log.error("没有下一题了,就结束了: {},uuid为:{}", date, phoneCallBackVO.getUuid()); |
| | | redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES); |
| | |
| | | return; |
| | | } else { |
| | | //就可以挂断电话了 |
| | | ServiceSubtask ss = new ServiceSubtask(); |
| | | ss.setId(serviceSubtask.getId()); |
| | | ss.setSendstate(6L); |
| | | serviceSubtaskMapper.updateServiceSubtask(ss); |
| | | |
| | | String date = simpleDateFormat1.format(new Date()); |
| | | log.info("就可以挂断电话了------: {},uuid为:{}", date, phoneCallBackVO.getUuid()); |
| | | redisCache.setCacheObject(phoneCallBackVO.getUuid() + "hangup", 1, 120, TimeUnit.MINUTES); |
| | |
| | | public PhoneCallBackYQVO phoneCallBackYQ(PhoneCallReqYQVO phoneCallReqYQVO) { |
| | | //判断是否挂机 |
| | | String hangupState = redisCache.getCacheObject(phoneCallReqYQVO.getUuid() + "- hangup"); |
| | | if (StringUtils.isNotEmpty(hangupState) && hangup.equals("1")) { |
| | | Object cacheObject1 = redisCache.getCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup"); |
| | | if (StringUtils.isNotEmpty(hangupState) && hangup.equals("1") || ObjectUtils.isNotEmpty(cacheObject1) && String.valueOf(cacheObject1).equals("1")) { |
| | | return new PhoneCallBackYQVO(); |
| | | } |
| | | if ("AsrCallback".equals(phoneCallReqYQVO.getOperate()) && phoneCallReqYQVO.getEnd_time() != null && phoneCallReqYQVO.getEnd_time() != -1) { |
| | | //处理挂断 |
| | | if (phoneCallReqYQVO.getAsrtext().contains("拨叫的用户正忙")) { |
| | | //判断 recordAccept-hungup 是否有值,如果有,则说明不用处理了,之前已经处理过了(recordAccept-hungup这个主要是给“通话记录用的,”) |
| | | Object cacheObject = redisCache.getCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup"); |
| | | if (ObjectUtils.isNotEmpty(cacheObject) && String.valueOf(cacheObject).equals("1")) { |
| | | return new PhoneCallBackYQVO(); |
| | | } |
| | | ServiceSubtask serviceSubtask2 = new ServiceSubtask(); |
| | | serviceSubtask2.setRemark("电话发送成功(患者挂断)"); |
| | | serviceSubtask2.setSenduuid(phoneCallReqYQVO.getUuid()); |
| | |
| | | req.put("caller", phoneCallReqYQVO.getPhone()); |
| | | HttpUtil.postJsonRequest(hangup, new Gson().toJson(req)); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- hangup", "1", 2, TimeUnit.MINUTES); |
| | | //先把默认的recordAccept-hungup删除,再更新 |
| | | redisCache.deleteObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup"); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup", "1", 10, TimeUnit.MINUTES); |
| | | //这个时候就需要走补偿机制了,先暂定走短信 |
| | | getSmsCompensate(Long.valueOf(phoneCallReqYQVO.getTaskid())); |
| | | return new PhoneCallBackYQVO(); |
| | | } |
| | | } |
| | |
| | | } else { |
| | | log.error("静默次数达到,挂掉电话:{}", num); |
| | | ServiceTask serviceTask1 = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | | ServiceSubtask ss = new ServiceSubtask(); |
| | | ss.setId(serviceSubtask.getId()); |
| | | ss.setSendstate(5L); |
| | | ss.setRemark("电话静默"); |
| | | serviceSubtaskMapper.updateServiceSubtask(ss); |
| | | //大与等于的话,直接挂断 |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setSilent_interval(ivrTaskTemplate.getSilencetime().intValue()); |
| | |
| | | } |
| | | return phoneCallBackYQVO; |
| | | } else if ("AsrCallback".equals(phoneCallReqYQVO.getOperate()) && phoneCallReqYQVO.getEnd_time() != null && phoneCallReqYQVO.getEnd_time() != -1) { |
| | | |
| | | //做一个标识,用来在通话详情接口里,判断是否有人接电话(value=2,表示有人接) |
| | | redisCache.deleteObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup"); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getTaskid() + "recordAccept-hungup", "2", 10, TimeUnit.MINUTES); |
| | | // 先对通话进行通用库匹配一次 |
| | | String extemplateID = ivrTaskTemplate.getSubmoduleID(); |
| | | if (StringUtils.isNotEmpty(extemplateID)) { |
| | |
| | | if (ObjectUtils.isNotEmpty(les)) { |
| | | //对匹配的结果处理一下(看看是不是需要挂机) |
| | | if (les.getIsEnd() != null && les.getIsEnd() == 1) { |
| | | ServiceSubtask ss = new ServiceSubtask(); |
| | | ss.setId(serviceSubtask.getId()); |
| | | ss.setSendstate(6L); |
| | | ss.setRemark("电话拨打已完成"); |
| | | serviceSubtaskMapper.updateServiceSubtask(ss); |
| | | //可以挂机了 |
| | | redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone()); |
| | | redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE"); |
| | |
| | | score = BigDecimal.valueOf(score).add(ivrTaskTemplateScriptVO.getIvrTaskScriptTargetoptionList().get(j).getScore()).doubleValue(); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "SCORE", score, 120, TimeUnit.MINUTES); |
| | | } |
| | | if (nextQuestion == null || nextQuestion == 0L) { |
| | | //如果下一题为空,或者为0,则挂机 |
| | | ServiceSubtask ss = new ServiceSubtask(); |
| | | ss.setId(serviceSubtask.getId()); |
| | | ss.setSendstate(6L); |
| | | ss.setRemark("电话拨打已完成"); |
| | | serviceSubtaskMapper.updateServiceSubtask(ss); |
| | | redisCache.deleteObject(serviceSubtask.getId() + "-" + serviceSubtask.getPhone()); |
| | | redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "SCORE"); |
| | | redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "PlayEventCallbackPlaystop"); |
| | | redisCache.deleteObject(phoneCallReqYQVO.getUuid() + "noVoice"); |
| | | //在redis中保存一下结束语,在调用挂电话的方法时删除 |
| | | ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid()); |
| | | redisCache.setCacheObject(phoneCallReqYQVO.getUuid() + "- jsy", serviceTask.getJsy(), 120, TimeUnit.MINUTES); |
| | | phoneCallBackYQVO.setType("text"); |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask.getJsy()); |
| | | //将结果写进detail表 |
| | | ServiceSubTaskDetailReq ssdReq = new ServiceSubTaskDetailReq(); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetailList2 = new ArrayList<>(); |
| | | serviceSubtaskDetailList.add(getServiceSubtaskDetail(phoneCallReqYQVO, ivrTaskTemplateScriptVO, serviceSubtask, ivrTaskTemplate)); |
| | | serviceSubTaskDetailReq.setServiceSubtaskDetailList(serviceSubtaskDetailList2); |
| | | saveQuestionAnswerPhone(ssdReq); |
| | | return phoneCallBackYQVO; |
| | | } |
| | | |
| | | for (IvrTaskTemplateScript script : ivrTaskTemplateScripts) { |
| | | if (script.getSort() == nextQuestion.intValue()) { |
| | |
| | | if (ObjectUtils.isNotEmpty(scoreObj)) score = (double) scoreObj; |
| | | serviceSubtask.setScore(BigDecimal.valueOf(score)); |
| | | serviceSubtask.setFinishtime(new Date()); |
| | | serviceSubtask.setSendstate(6L); |
| | | serviceSubtask.setRemark("电话拨打已完成"); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | //设置结束语 |
| | | phoneCallBackYQVO.setValue(phoneCallBackYQVO.getCommonValue() + serviceTask1.getJsy()); |
| | |
| | | if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj; |
| | | serviceSubtask.setScore(BigDecimal.valueOf(score)); |
| | | serviceSubtask.setFinishtime(new Date()); |
| | | serviceSubtask.setSendstate(6L); |
| | | serviceSubtask.setRemark("电话拨打已完成"); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | |
| | | //在redis中保存一下结束语,在调用挂电话的方法时删除 |
| | |
| | | if (ObjectUtils.isNotEmpty(scoreObj)) score = (Double) scoreObj; |
| | | serviceSubtask.setScore(BigDecimal.valueOf(score)); |
| | | serviceSubtask.setFinishtime(new Date()); |
| | | serviceSubtask.setRemark("电话拨打已完成"); |
| | | serviceSubtask.setSendstate(6L); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | |
| | | //去redis中,把该子任务ID删除 |
| | |
| | | i = serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } |
| | | } else { |
| | | for (ServiceSubtaskDetail serviceSubtaskDetail : serviceSubTaskDetailReq.getServiceSubtaskDetailList()) { |
| | | serviceSubtaskDetail.setCreateTime(new Date()); |
| | | //先根据子任务id,任务ID和问题序号查询一下,该问题是否已经有值,如果有值,直接修改,如果为空,直接插入 |
| | | ServiceSubtaskDetail ssd = new ServiceSubtaskDetail(); |
| | | ssd.setSubId(serviceSubtaskDetail.getSubId()); |
| | | ssd.setTaskid(serviceSubtaskDetail.getTaskid()); |
| | | ssd.setTemplatequestionnum(serviceSubtaskDetail.getTemplatequestionnum()); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetails = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(ssd); |
| | | if (CollectionUtils.isNotEmpty(serviceSubtaskDetails) && StringUtils.isNotEmpty(serviceSubtaskDetails.get(0).getMatchedtext())) { |
| | | serviceSubtaskDetail.setId(serviceSubtaskDetails.get(0).getId()); |
| | | serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } else { |
| | | i = serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail); |
| | | if (serviceSubTaskDetailReq != null && CollectionUtils.isNotEmpty(serviceSubTaskDetailReq.getServiceSubtaskDetailList())) { |
| | | for (ServiceSubtaskDetail serviceSubtaskDetail : serviceSubTaskDetailReq.getServiceSubtaskDetailList()) { |
| | | serviceSubtaskDetail.setCreateTime(new Date()); |
| | | //先根据子任务id,任务ID和问题序号查询一下,该问题是否已经有值,如果有值,直接修改,如果为空,直接插入 |
| | | ServiceSubtaskDetail ssd = new ServiceSubtaskDetail(); |
| | | ssd.setSubId(serviceSubtaskDetail.getSubId()); |
| | | ssd.setTaskid(serviceSubtaskDetail.getTaskid()); |
| | | ssd.setTemplatequestionnum(serviceSubtaskDetail.getTemplatequestionnum()); |
| | | List<ServiceSubtaskDetail> serviceSubtaskDetails = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(ssd); |
| | | if (CollectionUtils.isNotEmpty(serviceSubtaskDetails) && StringUtils.isNotEmpty(serviceSubtaskDetails.get(0).getMatchedtext())) { |
| | | serviceSubtaskDetail.setId(serviceSubtaskDetails.get(0).getId()); |
| | | serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } else { |
| | | i = serviceSubtaskDetailMapper.insertServiceSubtaskDetail(serviceSubtaskDetail); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | @Override |
| | | public Integer recordAccept(PhoneCallRecordVO phoneCallRecordVO) { |
| | | if (phoneCallRecordVO.getAnswered() != null && phoneCallRecordVO.getAnswered() == true) { |
| | | Object cacheObject = redisCache.getCacheObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup"); |
| | | if (phoneCallRecordVO.getHangup_cause().equals("NO_USER_RESPONSE") || ObjectUtils.isNotEmpty(cacheObject) && String.valueOf(cacheObject).equals("1")) { |
| | | //无人接听 |
| | | getSmsCompensate(Long.valueOf(phoneCallRecordVO.getTaskid())); |
| | | redisCache.deleteObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup"); |
| | | } else if (ObjectUtils.isNotEmpty(cacheObject) && String.valueOf(cacheObject).equals("2")) { |
| | | // if (phoneCallRecordVO.getAnswered() != null && phoneCallRecordVO.getAnswered() == true) { |
| | | log.error("有人接电话了,并且完了"); |
| | | //说明有人接了 |
| | | int startIndex = phoneCallRecordVO.getRecord_path().indexOf("voice") + "voice".length() + 1; // 加1是跳过/符号 |
| | |
| | | String result = phoneCallRecordVO.getRecord_path().substring(startIndex, endIndex); |
| | | //下载文件 |
| | | ftpService.downloadFolder("/" + LocalDate.now().toString(), profile + "/upload/vadio/voice/" + LocalDate.now().toString()); |
| | | redisCache.deleteObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup"); |
| | | } else { |
| | | //患者拒绝随访 |
| | | ServiceSubtask serviceSubtask = new ServiceSubtask(); |
| | | serviceSubtask.setRemark("电话接通成功,患者拒绝随访"); |
| | | serviceSubtask.setId(Long.valueOf(phoneCallRecordVO.getTaskid())); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | int startIndex = phoneCallRecordVO.getRecord_path().indexOf("voice") + "voice".length() + 1; // 加1是跳过/符号 |
| | | int endIndex = phoneCallRecordVO.getRecord_path().lastIndexOf("/"); |
| | | String result = phoneCallRecordVO.getRecord_path().substring(startIndex, endIndex); |
| | | //下载文件 |
| | | ftpService.downloadFolder("/" + LocalDate.now().toString(), profile + "/upload/vadio/voice/" + LocalDate.now().toString()); |
| | | redisCache.deleteObject(phoneCallRecordVO.getTaskid() + "recordAccept-hungup"); |
| | | } |
| | | |
| | | return 1; |
| | | } |
| | | |
| | |
| | | return serviceSubtaskDetail; |
| | | } |
| | | |
| | | private void getSmsCompensate(Long subTaskId) { |
| | | ServiceSubtask serviceSubtask = serviceSubtaskMapper.selectServiceSubtaskById(subTaskId); |
| | | RSAPublicKeyExample rsaPublicKeyExample = new RSAPublicKeyExample(); |
| | | String taskId = rsaPublicKeyExample.encryptedData(serviceSubtask.getTaskid().toString(), pub_key); |
| | | String patid = rsaPublicKeyExample.encryptedData(serviceSubtask.getPatid().toString(), pub_key); |
| | | ServiceOutPath serviceOutPath = new ServiceOutPath(); |
| | | serviceOutPath.setParam1(taskId); |
| | | serviceOutPath.setParam2(patid); |
| | | serviceOutPath.setCreateTime(new Date()); |
| | | iServiceOutPathService.insertServiceOutPath(serviceOutPath); |
| | | //转成16进制 |
| | | String format = String.format("%03X", serviceOutPath.getId()); |
| | | serviceOutPath.setRadix(format); |
| | | serviceOutPath.setUpdateTime(new Date()); |
| | | iServiceOutPathService.updateServiceOutPath(serviceOutPath); |
| | | SendMagParam sendMagParam = new SendMagParam(); |
| | | sendMagParam.setUrl(localIP + ":" + req_path + "/sf?p=" + format); |
| | | sendMagParam.setContent("【新华医院】您好,邀请您填写出院随访调查表,请点击" + sendMagParam.getUrl() + "填写。感谢您配合!"); |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("phone", serviceSubtask.getPhone()); |
| | | map.put("content", sendMagParam.getContent()); |
| | | String result = HttpUtil.postJsonRequest(xhsmsPath, new Gson().toJson(map)); |
| | | redisCache.setCacheObject(subTaskId + "recordAccept-hungup", "1", 10, TimeUnit.MINUTES); |
| | | if (StringUtils.isNotEmpty(serviceSubtask.getRemark())) serviceSubtask.setRemark("电话发送拒接,短信补偿发送成功"); |
| | | else serviceSubtask.setRemark("短信补偿发送成功"); |
| | | serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | } |
| | | } |