百度智能外呼对接。

This commit is contained in:
haown 2024-09-05 13:58:57 +08:00
parent 632309393b
commit 8f8d74d00c
14 changed files with 346 additions and 31 deletions

View File

@ -288,4 +288,6 @@ aiob:
url: https://aiob-open.baidu.com/api
accessKey: b6d2d73cdf2d4d7ca2ccc84968accdb3
secretKey: 9262d2fe32544eaabce18331bd5ca2c5
# 任务执行回调地址--测试
callBackUrl: http://8.131.93.145:54011/api/taskCallBack

View File

@ -52,6 +52,11 @@
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>

View File

@ -1,5 +1,7 @@
package com.xinelu.manage.controller.aibo;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.common.core.controller.BaseController;
import com.xinelu.common.core.domain.R;
import com.xinelu.manage.dto.aibo.CreateTaskDto;
@ -74,7 +76,7 @@ public class AIOBController extends BaseController {
*/
@ApiOperation("任务单通电话回调")
@PostMapping("/taskCallBack")
public R<String> taskCallBack(@RequestBody TaskCallbackDto taskCallbackDto) {
return R.ok(aiobService.taskCallBack(taskCallbackDto.getCallbackType(), taskCallbackDto.getData()));
public JSONObject taskCallBack(@RequestBody TaskCallbackDto taskCallbackDto) throws ClientException {
return aiobService.taskCallBack(taskCallbackDto.getCallbackType(), taskCallbackDto.getData());
}
}

View File

@ -106,6 +106,12 @@ public class SignPatientManageRouteNode extends BaseEntity {
@Excel(name = "电话内容", readConverterExp = "富文本存放整个节点的信息,包含标签画像的名称以及其它,标签画像名称使用特殊符号进行标记")
private String phoneNodeContent;
/**
* 爱医声平台任务查询返回JSON
*/
@ApiModelProperty(value = "爱医声平台任务查询返回JSON")
private String phoneResultJson;
/** 电话重拨次数重拨一次REDIAL_ONCE重拨二次REDIAL_TWICE不重播NOT_REPLAY */
@ApiModelProperty(value = "电话重拨次数重拨一次REDIAL_ONCE重拨二次REDIAL_TWICE不重播NOT_REPLAY")
@Excel(name = "电话重拨次数重拨一次REDIAL_ONCE重拨二次REDIAL_TWICE不重播NOT_REPLAY")
@ -394,4 +400,7 @@ public class SignPatientManageRouteNode extends BaseEntity {
@ApiModelProperty(value = "患者宣教阅读或问卷提交的时间")
@Excel(name = "患者宣教阅读或问卷提交的时间")
private LocalDateTime nodeFinishDate;
@ApiModelProperty(value = "第三方返回的任务ID")
private String taskIdExt;
}

View File

@ -59,6 +59,12 @@ public class CreateTaskDto {
*/
private List<Integer> numTypeFilterList;
private Boolean taskDataCallback;
/**
* 任务级回调地址设置
*/
private String callBackUrl;
/**
* 任务拨号完成后是否进入完成状态, 0:拨号完成后任务不结束 1:拨号完成后任务结束 默认值为1
*/

View File

@ -20,4 +20,6 @@ public interface ScriptInfoTaskInfoMapper {
*/
int insertScriptInfoTaskInfo(ScriptInfoTaskInfo scriptInfoTaskInfo);
int deleteScriptInfoTaskInfo();
}

View File

@ -1,5 +1,7 @@
package com.xinelu.manage.service.aibo;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.manage.dto.aibo.CreateTaskDto;
import com.xinelu.manage.dto.aibo.ImportTaskDto;
import com.xinelu.manage.dto.aibo.TaskCallbackDataDto;
@ -50,5 +52,13 @@ public interface IAIOBService {
*/
List<ImportTaskVo> importTask(ImportTaskDto importTaskDto);
String taskCallBack(Integer callbackType, TaskCallbackDataDto data);
/**
* @description 任务单执行回调方法
* @param callbackType 回调数据类型 0-任务呼叫单通电话回调 1-号码组终态回调 2-任务状态变更回调 3-实时呼叫单通电话回调
* @param data 任务单通电话回调传输data
* @return null
* @Author haown
* @Date 2024-9-2 14:20
*/
JSONObject taskCallBack(Integer callbackType, TaskCallbackDataDto data) throws ClientException;
}

View File

@ -1,20 +1,60 @@
package com.xinelu.manage.service.aibo.impl;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.common.config.AliYunSmsTwoConfig;
import com.xinelu.common.constant.PhoneMessageRemindConstants;
import com.xinelu.common.constant.TaskCreateTypeConstant;
import com.xinelu.common.constant.TaskStatisticsTypeConstants;
import com.xinelu.common.core.redis.RedisCache;
import com.xinelu.common.enums.ErrorStatusEnum;
import com.xinelu.common.enums.NodeExecuteResultStatusEnum;
import com.xinelu.common.enums.NodeExecuteStatusEnum;
import com.xinelu.common.enums.PhoneRedialTimesEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.StringUtils;
import com.xinelu.manage.domain.patientinfo.PatientInfo;
import com.xinelu.manage.domain.patienttaskexecuterecord.PatientTaskExecuteRecord;
import com.xinelu.manage.domain.phonedialrecord.PhoneDialRecord;
import com.xinelu.manage.domain.scriptInfo.ScriptInfo;
import com.xinelu.manage.domain.signpatientmanageroute.SignPatientManageRoute;
import com.xinelu.manage.domain.signpatientmanageroutenode.SignPatientManageRouteNode;
import com.xinelu.manage.domain.signpatientrecord.SignPatientRecord;
import com.xinelu.manage.domain.textmessage.TextMessage;
import com.xinelu.manage.dto.aibo.CreateTaskDto;
import com.xinelu.manage.dto.aibo.CustomerInfoDto;
import com.xinelu.manage.dto.aibo.ImportTaskDto;
import com.xinelu.manage.dto.aibo.TaskCallbackDataDto;
import com.xinelu.manage.dto.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
import com.xinelu.manage.dto.smssend.SmsInfoDTO;
import com.xinelu.manage.mapper.labelfieldcontent.LabelFieldContentMapper;
import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper;
import com.xinelu.manage.mapper.patienttaskexecuterecord.PatientTaskExecuteRecordMapper;
import com.xinelu.manage.mapper.phonedialrecord.PhoneDialRecordMapper;
import com.xinelu.manage.mapper.scriptInfo.ScriptInfoMapper;
import com.xinelu.manage.mapper.signpatientmanageroute.SignPatientManageRouteMapper;
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
import com.xinelu.manage.mapper.signpatientrecord.SignPatientRecordMapper;
import com.xinelu.manage.mapper.textmessage.TextMessageMapper;
import com.xinelu.manage.service.aibo.IAIOBService;
import com.xinelu.manage.service.patienttaskstatistics.IPatientTaskStatisticsService;
import com.xinelu.manage.service.signpatientmanageroute.ISignPatientManageRouteService;
import com.xinelu.manage.vo.aibo.ImportTaskVo;
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
@ -29,6 +69,7 @@ import org.springframework.web.client.RestTemplate;
* @author: haown
* @create: 2024-08-22 09:54
**/
@Slf4j
@Service
public class AIOBServiceImpl implements IAIOBService {
@Value("${aiob.url}")
@ -43,6 +84,31 @@ public class AIOBServiceImpl implements IAIOBService {
@Resource
private RedisCache redisCache;
@Resource
private SignPatientRecordMapper signPatientRecordMapper;
@Resource
private SignPatientManageRouteMapper signPatientManageRouteMapper;
@Resource
private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
@Resource
private PhoneDialRecordMapper phoneDialRecordMapper;
@Resource
private AliYunSmsTwoConfig aliYunSmsTwoConfig;
@Resource
private ISignPatientManageRouteService signPatientManageRouteService;
@Resource
private TextMessageMapper textMessageMapper;
@Resource
private PatientTaskExecuteRecordMapper patientTaskExecuteRecordMapper;
@Resource
private IPatientTaskStatisticsService patientTaskStatisticsService;
@Resource
private PatientInfoMapper patientInfoMapper;
@Resource
private LabelFieldContentMapper labelFieldContentMapper;
@Resource
private ScriptInfoMapper scriptInfoMapper;
/**
* @description 获取外呼平台accessToken
* @return 智能外呼平台 accessToken
@ -71,7 +137,7 @@ public class AIOBServiceImpl implements IAIOBService {
// accessToken放入redis缓存
accessToken = data.getString("accessToken");
// 有效期30天
int expires_in = object.getInteger("expires_in");
int expires_in = data.getInteger("expiresTime");
redisCache.setCacheObject("AIOBAssessToken", accessToken, expires_in, TimeUnit.MINUTES);
}
return accessToken;
@ -141,7 +207,7 @@ public class AIOBServiceImpl implements IAIOBService {
.fluentPut("taskStatus", taskStatus);
HttpEntity<JSONObject> requestEntity = new HttpEntity<>(jsonObject, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.exchange(url + "/v3/console/realtime/status/create", HttpMethod.POST, requestEntity, String.class);
ResponseEntity<String> responseEntity = restTemplate.exchange(url + "/v3/console/apitask/task/status/update", HttpMethod.POST, requestEntity, String.class);
JSONObject object = JSON.parseObject(responseEntity.getBody());
if (object == null || object.getInteger("code") == null || object.getInteger("code") != 200) {
throw new ServiceException("修改任务状态失败," + object.getString("msg"));
@ -179,7 +245,7 @@ public class AIOBServiceImpl implements IAIOBService {
}
JSONObject data = object.getJSONObject("data");
JSONArray resList = data.getJSONArray("retList");
JSONArray resList = data.getJSONArray("resList");
List<ImportTaskVo> importTaskList = Arrays.asList(resList.toArray(ImportTaskVo.class));
return importTaskList;
// {
@ -206,8 +272,17 @@ public class AIOBServiceImpl implements IAIOBService {
// }
}
/**
* @description 任务单执行回调方法
* @param callbackType 回调数据类型 0-任务呼叫单通电话回调 1-号码组终态回调 2-任务状态变更回调 3-实时呼叫单通电话回调
* @param data 任务单通电话回调传输data
* @return null
* @Author haown
* @Date 2024-9-2 14:20
*/
@Override
public String taskCallBack(Integer callbackType, TaskCallbackDataDto data) {
public JSONObject taskCallBack(Integer callbackType, TaskCallbackDataDto data) throws ClientException {
//{"extJson":"623","taskId":"3892402966495232","tenantId":3849515568332800}
//TaskCallbackDataDto(sessionId=3874887150206976_2e1ae4e5ee0a4513b61d2411523f7b9b, tenantId=3849515568332800,
// taskId=3874887150206976, taskName=测试20240829, robotId=11a05202-12a4-437a-b989-43235b920a2f,
// robotName=慢病用药回访, memberId=3875110220070912, mobile=15166940975, callTimes=1,
@ -222,6 +297,155 @@ public class AIOBServiceImpl implements IAIOBService {
// {"role":"speech","timestamp":1724917725993,"content":"是的","contextText":"祝您早日康复。","sn":"0e5c9c4e65db11ef_6_1","intent":"sys_yes","start":"00:27.505","stop":"00:29.637","timeLen":2132,"interrupted":false,"silent":false,"nodeInfo":"eyJwcm9jZXNzTmFtZSI6IuaFoueXheeUqOiNr+Wbnuiuv+ivneacryIsIm5vZGVOYW1lIjoi5oyJ5pe25pyN6I2v6IqC54K5X3Bxd2RkcDBpIiwiaW50ZW50Ijoi6IKv5a6a5oSP5Zu+IiwiZW50aXR5IjpbXSwic3lzdGVtRXZlbnQiOiIiLCJmYXEiOiIifQ=="}],
// durationTimeLen=42, ringingTimeLen=9, talkingTimeLen=29, startTime=1724917686000, ringStartTime=1724917688000, talkingStartTime=1724917698000, endTime=1724917728000, intent=null, action=[HANGUP], isRobotHangup=true,
// dialogVar={"departmentName":"山东省立医院","patientName":"李四"}, smsVar=null, extJson=测试2, transResult=0)
return data.getTaskId();
JSONObject retObj = new JSONObject();
retObj.fluentPut("code", 200).fluentPut("msg", "success");
if (callbackType == 0) {
// 是否发送短信标识
boolean needSendSms = false;
// 根据id查询任务
SignPatientManageRouteNode signPatientManageRouteNode = signPatientManageRouteNodeMapper.selectSignPatientManageRouteNodeById(Long.valueOf(data.getExtJson()));
if (ObjectUtils.isNotEmpty(signPatientManageRouteNode)) {
// 标记任务执行状态
signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.EXECUTED.getInfo());
// 获取电话已拨打次数
PhoneDialRecord phoneDialRecordQuery = new PhoneDialRecord();
phoneDialRecordQuery.setManageRouteNodeId(signPatientManageRouteNode.getId());
List<PhoneDialRecord> phoneDialRecordList = phoneDialRecordMapper.selectPhoneDialRecordList(phoneDialRecordQuery);
// 电话拨打未成功判断是否需要重拨电话拨打成功设置电话拨通情况为成功
if (data.getEndType() != null && data.getEndType() == 0) {//接通状态1-已接通 0-未接通
// 已经拨打的次数
int dialCount = CollectionUtils.isEmpty(phoneDialRecordList) ? 0 : phoneDialRecordList.size() + 1;
if (PhoneRedialTimesEnum.getValueByInfo(signPatientManageRouteNode.getPhoneRedialTimes()).getValue() + 1 > dialCount) {
// 需要重拨-导入名单
uploadCustomerInfoList(signPatientManageRouteNode, data.getTaskId());
} else {
// 不需要重拨设置电话拨通情况
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
}
//电话短信提醒
if (StringUtils.equals(PhoneMessageRemindConstants.NOT_CONNECTED_SEND_MESSAGE, signPatientManageRouteNode.getPhoneMessageRemind())) {
// 发送短信
needSendSms = true;
}
} else {
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
if (StringUtils.equals(PhoneMessageRemindConstants.CONNECTED_SEND_MESSAGE, signPatientManageRouteNode.getPhoneMessageRemind())) {
// 发送短信
needSendSms = true;
}
// 记录通话详情
signPatientManageRouteNode.setPhoneResultJson(com.alibaba.fastjson.JSON.toJSONString(data, SerializerFeature.WriteMapNullValue));
}
signPatientManageRouteNodeMapper.updateSignPatientManageRouteNode(signPatientManageRouteNode);
PatientTaskExecuteRecord patientTaskExecuteRecord = new PatientTaskExecuteRecord();
BeanUtils.copyProperties(signPatientManageRouteNode, patientTaskExecuteRecord);
SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(signPatientManageRouteNode.getManageRouteId());
if (ObjectUtils.isNotEmpty(signPatientManageRoute)) {
patientTaskExecuteRecord.setPatientId(signPatientManageRoute.getPatientId());
patientTaskExecuteRecord.setPatientName(signPatientManageRoute.getPatientName());
// 就诊记录
SignPatientRecord signPatientRecord = signPatientRecordMapper.selectByPrimaryKey(signPatientManageRoute.getSignPatientRecordId());
if (ObjectUtils.isNotEmpty(signPatientRecord)) {
patientTaskExecuteRecord.setVisitRecordId(signPatientRecord.getPatientVisitRecordId());
}
// 发送短信
if (needSendSms) {
sendSms(signPatientManageRoute.getPatientId(), signPatientManageRouteNode);
}
}
// 增加任务执行记录
patientTaskExecuteRecord.setManageRouteNodeId(signPatientManageRouteNode.getId());
patientTaskExecuteRecord.setManageRouteNodeName(signPatientManageRouteNode.getRouteNodeName());
patientTaskExecuteRecord.setExecuteResult(data.getEndTypeReason());
patientTaskExecuteRecord.setExecuteType(TaskCreateTypeConstant.MANUAL_MATCHE);
patientTaskExecuteRecord.setExecuteTime(LocalDateTime.now());
patientTaskExecuteRecord.setCreateTime(LocalDateTime.now());
// 增加电话拨打记录
PhoneDialRecord phoneDialRecord = new PhoneDialRecord();
phoneDialRecord.setPatientId(signPatientManageRoute.getPatientId());
phoneDialRecord.setManageRouteNodeId(signPatientManageRouteNode.getId());
phoneDialRecord.setPatientPhone(data.getMobile());
phoneDialRecord.setDialTime(LocalDateTime.now());
phoneDialRecord.setPhoneTemplateId(signPatientManageRouteNode.getScriptInfoId() + "");
phoneDialRecord.setPhoneDialMethod(signPatientManageRouteNode.getPhoneDialMethod());
phoneDialRecord.setErrorCode(data.getEndType() == 0 ? 1L : 0);
phoneDialRecord.setErrorStatus(data.getEndType() == 0 ? ErrorStatusEnum.fail.getValue() : ErrorStatusEnum.success.getValue());
phoneDialRecord.setCreateTime(LocalDateTime.now());
phoneDialRecordMapper.insertPhoneDialRecord(phoneDialRecord);
// 修改任务统计表数据
if (patientTaskExecuteRecordMapper.insertPatientTaskExecuteRecord(patientTaskExecuteRecord) > 0) {
// 任务统计表修改
patientTaskStatisticsService.updateNum(signPatientManageRoute.getPatientId(), TaskStatisticsTypeConstants.TASK_EXECUTE_NUM, 1);
}
}
}
return retObj;
}
private void sendSms(Long patientId, SignPatientManageRouteNode signPatientManageRouteNode) throws ClientException {
TextMessage textMessage = textMessageMapper.selectTextMessageById(signPatientManageRouteNode.getPhoneMessageTemplateId());
if (ObjectUtils.isNotEmpty(textMessage)) {
// 发送短信
SmsInfoDTO smsInfoDTO = new SmsInfoDTO();
String patientPhone = signPatientManageRouteMapper.selectPatientPhone(patientId);
smsInfoDTO.setPhoneNumbers(patientPhone);
smsInfoDTO.setSignName(aliYunSmsTwoConfig.getSignName());
smsInfoDTO.setTemplateCode(textMessage.getTextMessageId());
Boolean b = signPatientManageRouteService.sendSms(smsInfoDTO);
//发送记录
PatientQuestionSubmitResultDTO dto = new PatientQuestionSubmitResultDTO();
dto.setPatientId(patientId);
dto.setPatientPhone(patientPhone);
dto.setManageRouteNodeId(signPatientManageRouteNode.getId());
dto.setPhoneMessageTemplateCode(textMessage.getTextMessageId());
dto.setPhoneMessageTemplateContent(signPatientManageRouteNode.getPhoneMessageTemplateContent());
signPatientManageRouteService.shortMessageSendRecordExtracted(dto, LocalDateTime.now(), b, "AI");
if (!b) {
log.info("短信发送失败");
} else {
log.info("短信发送成功");
}
} else {
log.info("短信发送成功");
}
}
private void uploadCustomerInfoList(SignPatientManageRouteNode node, String taskId) {
CustomerInfoDto customerInfoDto = new CustomerInfoDto();
List<CustomerInfoDto> customerInfoList = new ArrayList<>();
customerInfoDto.setExtJson(node.getId() + "");
SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(node.getManageRouteId());
PatientInfo patientInfo = patientInfoMapper.selectPatientInfoById(signPatientManageRoute.getPatientId());
customerInfoDto.setMobile(patientInfo.getPatientPhone());
// 查询患者画像信息
List<LabelFieldInfoContentVo> labelFieldContentList = labelFieldContentMapper.selectByPatientId(patientInfo.getId());
ScriptInfo scriptInfo = scriptInfoMapper.selectScriptInfoById(node.getScriptInfoId());
// 处理变量
JSONObject jsonObject = new JSONObject();
if (StringUtils.isNotBlank(scriptInfo.getVariables())) {
List<String> variables = Arrays.asList(scriptInfo.getVariables().split("|"));
variables.forEach(variable -> {
LabelFieldInfoContentVo labelFieldContent = labelFieldContentList.stream().filter(s -> Objects.equals(s.getFieldCode(), variable.replaceAll("_", "").toUpperCase())).findFirst().orElse(null);
jsonObject.fluentPut(variable, ObjectUtils.isEmpty(labelFieldContent) ? "" : labelFieldContent.getFieldValue());
});
}
customerInfoDto.setVar(jsonObject);
customerInfoList.add(customerInfoDto);
// 上传名单
ImportTaskDto importTaskDto = new ImportTaskDto();
importTaskDto.setTaskId(taskId);
importTaskDto.setSecretType(2);
importTaskDto.setCustomerInfoList(customerInfoList);
importTask(importTaskDto);
}
}

View File

@ -121,5 +121,5 @@ public interface ISignPatientManageRouteService {
Boolean sendSms(SmsInfoDTO smsInfoDTO) throws ClientException, ServiceException;
void shortMessageSendRecordExtracted(PatientQuestionSubmitResultDTO dto, LocalDateTime time, Boolean b);
void shortMessageSendRecordExtracted(PatientQuestionSubmitResultDTO dto, LocalDateTime time, Boolean b, String createBy);
}

View File

@ -426,7 +426,7 @@ public class SignPatientManageRouteServiceImpl implements ISignPatientManageRout
smsInfoDTO.setTemplateCode(dto.getPhoneMessageTemplateCode());
Boolean b = sendSms(smsInfoDTO);
//发送记录
shortMessageSendRecordExtracted(dto, time, b);
shortMessageSendRecordExtracted(dto, time, b, null);
if (!b) {
log.info("短信发送失败");
} else {
@ -496,7 +496,7 @@ public class SignPatientManageRouteServiceImpl implements ISignPatientManageRout
* @param b 状态
*/
@Override
public void shortMessageSendRecordExtracted(PatientQuestionSubmitResultDTO dto, LocalDateTime time, Boolean b) {
public void shortMessageSendRecordExtracted(PatientQuestionSubmitResultDTO dto, LocalDateTime time, Boolean b, String createBy) {
ShortMessageSendRecord shortMessageSendRecord = new ShortMessageSendRecord();
shortMessageSendRecord.setPatientId(dto.getPatientId());
shortMessageSendRecord.setPatientPhone(dto.getPatientPhone());
@ -512,7 +512,7 @@ public class SignPatientManageRouteServiceImpl implements ISignPatientManageRout
shortMessageSendRecord.setErrorCode(0L);
shortMessageSendRecord.setErrorStatus(ErrorStatusEnum.success.getValue());
}
shortMessageSendRecord.setCreateBy(SecurityUtils.getUsername());
shortMessageSendRecord.setCreateBy(StringUtils.isBlank(createBy) ? SecurityUtils.getUsername() : createBy);
shortMessageSendRecord.setCreateTime(time);
shortMessageSendRecordMapper.insertShortMessageSendRecord(shortMessageSendRecord);
}

View File

@ -224,7 +224,7 @@ public class RobotPublishServiceImpl implements IRobotPublishService {
dto.setManageRouteNodeId(signPatientManageRouteNode.getId());
dto.setPhoneMessageTemplateCode(textMessage.getTextMessageId());
dto.setPhoneMessageTemplateContent(signPatientManageRouteNode.getPhoneMessageTemplateContent());
signPatientManageRouteService.shortMessageSendRecordExtracted(dto, LocalDateTime.now(), b);
signPatientManageRouteService.shortMessageSendRecordExtracted(dto, LocalDateTime.now(), b, "AI");
if (!b) {
log.info("短信发送失败");

View File

@ -51,4 +51,9 @@
</if>
</trim>
</insert>
<delete id="deleteScriptInfoTaskInfo">
delete
from script_info_task_info
</delete>
</mapper>

View File

@ -22,6 +22,7 @@
<result property="phoneTemplateId" column="phone_template_id"/>
<result property="phoneTemplateName" column="phone_template_name"/>
<result property="phoneNodeContent" column="phone_node_content"/>
<result property="phoneResultJson" column="phone_result_json"/>
<result property="phoneRedialTimes" column="phone_redial_times"/>
<result property="phoneTimeInterval" column="phone_time_interval"/>
<result property="phoneMessageRemind" column="phone_message_remind"/>
@ -80,10 +81,11 @@
<result property="officialNodeExecuteResultStatus" column="official_node_execute_result_status"/>
<result property="appletNodeExecuteResultStatus" column="applet_node_execute_result_status"/>
<result property="nodeFinishDate" column="node_finish_date"/>
<result property="taskIdExt" column="task_id_ext"/>
</resultMap>
<sql id="selectSignPatientManageRouteNodeVo">
select id, manage_route_id, manage_route_name, route_node_id, route_node_name, route_node_day, task_type, task_status, task_subdivision, task_node_type, second_classify_describe, execute_time, phone_push_sign, script_info_id, phone_template_id, phone_template_name, phone_node_content, phone_redial_times, phone_time_interval, phone_message_remind, phone_message_template_id, phone_message_template_name,phone_message_template_content,question_info_id, questionnaire_name, questionnaire_content, question_expiration_date, propaganda_info_id, propaganda_title, propaganda_content, message_push_sign, message_template_id, message_template_code, message_template_name, message_preview, message_node_content, official_push_sign, official_template_id, official_template_code, official_template_name, official_remind_content, official_node_content, follow_template_id, follow_template_name, applet_push_sign, applet_template_id, applet_template_code, applet_template_name, applet_remind_content, applet_prompt_description, applet_node_content, route_check_status, route_check_person, route_check_date, route_check_remark, route_node_remark, node_execute_status, route_handle_remark, route_handle_id, route_handle_person, route_link,text_remind_content, node_content,message_status, del_flag, create_by, create_time, update_by, update_time, phone_dial_method, phone_node_execute_result_status, message_node_execute_result_status, official_node_execute_result_status, applet_node_execute_result_status, node_finish_date from sign_patient_manage_route_node
select id, manage_route_id, manage_route_name, route_node_id, route_node_name, route_node_day, task_type, task_status, task_subdivision, task_node_type, second_classify_describe, execute_time, phone_push_sign, script_info_id, phone_template_id, phone_template_name, phone_node_content,phone_result_json, phone_redial_times, phone_time_interval, phone_message_remind, phone_message_template_id, phone_message_template_name,phone_message_template_content,question_info_id, questionnaire_name, questionnaire_content, question_expiration_date, propaganda_info_id, propaganda_title, propaganda_content, message_push_sign, message_template_id, message_template_code, message_template_name, message_preview, message_node_content, official_push_sign, official_template_id, official_template_code, official_template_name, official_remind_content, official_node_content, follow_template_id, follow_template_name, applet_push_sign, applet_template_id, applet_template_code, applet_template_name, applet_remind_content, applet_prompt_description, applet_node_content, route_check_status, route_check_person, route_check_date, route_check_remark, route_node_remark, node_execute_status, route_handle_remark, route_handle_id, route_handle_person, route_link,text_remind_content, node_content,message_status, del_flag, create_by, create_time, update_by, update_time, phone_dial_method, phone_node_execute_result_status, message_node_execute_result_status, official_node_execute_result_status, applet_node_execute_result_status, node_finish_date, task_id_ext from sign_patient_manage_route_node
</sql>
<select id="selectSignPatientManageRouteNodeList" parameterType="com.xinelu.manage.dto.signpatientmanageroutenode.SignPatientManageRouteNodeDto" resultMap="SignPatientManageRouteNodeResult">
@ -112,7 +114,7 @@
and task_status = #{taskStatus}
</if>
<if test="taskNodeType != null and taskNodeType != ''">
and task_node_type = #{taskStatus}
and task_node_type = #{taskNodeType}
</if>
<if test="taskTypeList != null and taskTypeList.size > 0">
and
@ -160,7 +162,7 @@
resultMap="SignPatientManageRouteNodeResult">
select node.id, node.manage_route_id, node.manage_route_name, node.route_node_id, node.route_node_name, node.route_node_day, node.task_type,
node.task_status, node.task_subdivision,node.second_classify_describe, node.execute_time, node.phone_push_sign, node.script_info_id,
node.phone_template_id, node.phone_template_name, node.phone_node_content, node.phone_redial_times, node.phone_time_interval,
node.phone_template_id, node.phone_template_name, node.phone_node_content, node.phone_result_json, node.phone_redial_times, node.phone_time_interval,
node.phone_message_remind, node.phone_message_template_id, node.phone_message_template_name,node.phone_message_template_content,
node.question_info_id, node.questionnaire_name, node.questionnaire_content, node.question_expiration_date,
node.propaganda_info_id, node.propaganda_title, node.propaganda_content,node.follow_template_id, node.follow_template_name,
@ -242,6 +244,8 @@
</if>
<if test="phoneNodeContent != null">phone_node_content,
</if>
<if test="phoneResultJson != null">phone_result_json,
</if>
<if test="phoneRedialTimes != null">phone_redial_times,
</if>
<if test="phoneTimeInterval != null">phone_time_interval,
@ -348,6 +352,8 @@
</if>
<if test="followTemplateName != null">follow_template_name,
</if>
<if test="taskIdExt != null">task_id_ext,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="manageRouteId != null">#{manageRouteId},
@ -382,6 +388,8 @@
</if>
<if test="phoneNodeContent != null">#{phoneNodeContent},
</if>
<if test="phoneResultJson != null">#{phoneResultJson},
</if>
<if test="phoneRedialTimes != null">#{phoneRedialTimes},
</if>
<if test="phoneTimeInterval != null">#{phoneTimeInterval},
@ -488,27 +496,29 @@
</if>
<if test="followTemplateName != null">#{followTemplateName},
</if>
<if test="taskIdExt != null">#{taskIdExt},
</if>
</trim>
</insert>
<insert id="insertBatch">
insert into sign_patient_manage_route_node(manage_route_id, manage_route_name, route_node_id, route_node_name, route_node_day, task_type, task_status, task_subdivision, task_node_type, second_classify_describe,
execute_time, phone_push_sign, script_info_id, phone_template_id, phone_template_name, phone_node_content, phone_redial_times, phone_time_interval, phone_message_remind, phone_message_template_id,
execute_time, phone_push_sign, script_info_id, phone_template_id, phone_template_name, phone_node_content, phone_result_json, phone_redial_times, phone_time_interval, phone_message_remind, phone_message_template_id,
phone_message_template_name, phone_message_template_content,question_info_id, questionnaire_name, questionnaire_content, question_expiration_date, propaganda_info_id, propaganda_title, propaganda_content, message_push_sign,
message_template_id, message_template_code, message_template_name, message_preview, message_node_content, official_push_sign, official_template_id, official_template_code,official_template_name, official_remind_content,
official_node_content, applet_push_sign, applet_template_id, applet_template_code, applet_template_name, applet_remind_content, applet_prompt_description, applet_node_content,
route_check_status, route_check_person, route_check_date, route_check_remark, route_node_remark, node_execute_status, route_handle_remark,phone_connect_status,
route_handle_id, route_handle_person, route_link, text_remind_content,node_content, del_flag, create_by, create_time, update_by, update_time,phone_dial_method,follow_template_id, follow_template_name)
route_handle_id, route_handle_person, route_link, text_remind_content,node_content, del_flag, create_by, create_time, update_by, update_time,phone_dial_method,follow_template_id, follow_template_name, task_id_ext)
values
<foreach collection="nodeList" item="item" separator=",">
(#{item.manageRouteId},#{item.manageRouteName},#{item.routeNodeId},#{item.routeNodeName},#{item.routeNodeDay},#{item.taskType},#{item.taskStatus},#{item.taskSubdivision},#{item.taskNodeType},#{item.secondClassifyDescribe},
#{item.executeTime},#{item.phonePushSign},#{item.scriptInfoId},#{item.phoneTemplateId},#{item.phoneTemplateName},#{item.phoneNodeContent},#{item.phoneRedialTimes},#{item.phoneTimeInterval},#{item.phoneMessageRemind},#{item.phoneMessageTemplateId},
#{item.executeTime},#{item.phonePushSign},#{item.scriptInfoId},#{item.phoneTemplateId},#{item.phoneTemplateName},#{item.phoneNodeContent},#{phoneResultJson},#{item.phoneRedialTimes},#{item.phoneTimeInterval},#{item.phoneMessageRemind},#{item.phoneMessageTemplateId},
#{item.phoneMessageTemplateName},#{item.phoneMessageTemplateContent},
#{item.questionInfoId},#{item.questionnaireName},#{item.questionnaireContent},#{item.questionExpirationDate},#{item.propagandaInfoId},#{item.propagandaTitle},#{item.propagandaContent},#{item.messagePushSign},
#{item.messageTemplateId}, #{item.messageTemplateCode},
#{item.messageTemplateName},#{item.messagePreview},#{item.messageNodeContent},#{item.officialPushSign},#{item.officialTemplateId},#{item.officialTemplateCode},#{item.officialTemplateName},#{item.officialRemindContent},#{item.officialNodeContent},
#{item.appletPushSign},#{item.appletTemplateId},#{item.appletTemplateCode},#{item.appletTemplateName},#{item.appletRemindContent},#{item.appletPromptDescription},#{item.appletNodeContent},
#{item.routeCheckStatus},#{item.routeCheckPerson},#{item.routeCheckDate},#{item.routeCheckRemark},#{item.routeNodeRemark},#{item.nodeExecuteStatus},#{item.routeHandleRemark},#{item.phoneConnectStatus},
#{item.routeHandleId},#{item.routeHandlePerson},#{item.routeLink},#{item.textRemindContent},#{item.nodeContent},0,#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime},#{item.phoneDialMethod},#{item.followTemplateId},#{item.followTemplateName})
#{item.routeHandleId},#{item.routeHandlePerson},#{item.routeLink},#{item.textRemindContent},#{item.nodeContent},0,#{item.createBy},#{item.createTime},#{item.updateBy},#{item.updateTime},#{item.phoneDialMethod},#{item.followTemplateId},#{item.followTemplateName},#{taskIdExt})
</foreach>
</insert>
<update id="updateSignPatientManageRouteNode" parameterType="SignPatientManageRouteNode">
@ -562,6 +572,9 @@
<if test="phoneNodeContent != null">phone_node_content =
#{phoneNodeContent},
</if>
<if test="phoneResultJson != null">phone_result_json =
#{phoneResultJson},
</if>
<if test="phoneRedialTimes != null">phone_redial_times =
#{phoneRedialTimes},
</if>
@ -739,6 +752,9 @@
<if test="nodeFinishDate != null">node_finish_date =
#{nodeFinishDate},
</if>
<if test="taskIdExt != null">task_id_ext =
#{taskIdExt},
</if>
</trim>
where id = #{id}
</update>

View File

@ -26,6 +26,7 @@ import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRout
import com.xinelu.manage.mapper.signpatientrecord.SignPatientRecordMapper;
import com.xinelu.manage.service.aibo.IAIOBService;
import com.xinelu.manage.service.signpatientmanageroutenode.ISignPatientManageRouteNodeService;
import com.xinelu.manage.vo.aibo.ImportTaskVo;
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -40,10 +41,11 @@ import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @description: 爱医声上传任务定时任务
* @description: 百度智能外呼上传任务定时任务
* @author: haown
* @create: 2024-08-19 13:58
**/
@ -51,6 +53,8 @@ import org.springframework.stereotype.Component;
@Component("UploadRobotPublishTask")
public class UploadRobotPublishTask {
@Value("${aiob.callBackUrl}")
private String callBackUrl;
@Resource
private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
@Resource
@ -72,8 +76,11 @@ public class UploadRobotPublishTask {
@Resource
private LabelFieldContentMapper labelFieldContentMapper;
/**
* @description 创建百度智能外呼任务并导入客户名单
* @Author haown
* @Date 2024-9-5 13:55
*/
public void uploadRobotPublishTask() {
log.info("开始执行百度智能外呼创建任务定时任务......");
// 查找需要当天执行的AI打电话任务
@ -89,13 +96,14 @@ public class UploadRobotPublishTask {
SignPatientRecord signPatientRecord = signPatientRecordMapper.selectByPrimaryKey(signPatientManageRoute.getSignPatientRecordId());
PatientVisitRecord patientVisitRecord = patientVisitRecordMapper.selectPatientVisitRecordById(signPatientRecord.getPatientVisitRecordId());
LocalDateTime executeTime = signPatientManageRouteNodeService.getExecuteTime(node.getExecuteTime(), node.getRouteNodeName(), node.getRouteNodeDay(), patientVisitRecord);
if (executeTime.toLocalDate().isBefore(LocalDate.now())) {
if (executeTime.toLocalDate().isBefore(LocalDate.now())|| executeTime.toLocalDate().isEqual(LocalDate.now())) {
executeNodeList.add(node);
}
});
if (CollectionUtils.isNotEmpty(executeNodeList)) {
// 按照话术id分组每个话术id对应不同的机器人id, 每个机器人每天创建一条任务
Map<Long, List<SignPatientManageRouteNode>> groupByScriptInfo = executeNodeList.stream().collect(Collectors.groupingBy(SignPatientManageRouteNode::getScriptInfoId));
Map<Long, List<SignPatientManageRouteNode>> groupByScriptInfo = executeNodeList.stream().filter(node -> node.getScriptInfoId() != null).collect(Collectors.groupingBy(SignPatientManageRouteNode::getScriptInfoId));
// 根据机器人id查询智能外呼系统的任务id
for (Long scriptInfoId : groupByScriptInfo.keySet()) {
ScriptInfo scriptInfo = scriptInfoMapper.selectScriptInfoById(scriptInfoId);
@ -103,6 +111,7 @@ public class UploadRobotPublishTask {
if (StringUtils.isBlank(taskId)) {
// 没有任务则创建任务
if (ObjectUtils.isNotEmpty(scriptInfo)) {
log.info("创建任务......");
CreateTaskDto createTaskDto = new CreateTaskDto();
createTaskDto.setTaskName(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + scriptInfo.getScriptName());
createTaskDto.setRobotId(scriptInfo.getRobotPublishId());
@ -110,7 +119,12 @@ public class UploadRobotPublishTask {
createTaskDto.setDialEndDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
createTaskDto.setForbidDialDate(Arrays.asList(99));
createTaskDto.setNumTypeFilterList(Arrays.asList(1,2));
createTaskDto.setTaskDataCallback(true);
createTaskDto.setCallBackUrl(callBackUrl);
taskId = aiobService.createTask(createTaskDto);
// 开启任务
log.info("开启任务......");
aiobService.updateTaskStatus(taskId, 2);
ScriptInfoTaskInfo scriptInfoTaskInfo = new ScriptInfoTaskInfo();
scriptInfoTaskInfo.setScriptInfoId(scriptInfoId);
@ -134,7 +148,7 @@ public class UploadRobotPublishTask {
// 处理变量
JSONObject jsonObject = new JSONObject();
if (StringUtils.isNotBlank(scriptInfo.getVariables())) {
List<String> variables = Arrays.asList(scriptInfo.getVariables().split("|"));
List<String> variables = Arrays.asList(scriptInfo.getVariables().split("\\|"));
variables.forEach(variable -> {
LabelFieldInfoContentVo labelFieldContent = labelFieldContentList.stream().filter(s -> Objects.equals(s.getFieldCode(), variable.replaceAll("_", "").toUpperCase())).findFirst().orElse(null);
jsonObject.fluentPut(variable, ObjectUtils.isEmpty(labelFieldContent) ? "" : labelFieldContent.getFieldValue());
@ -146,16 +160,36 @@ public class UploadRobotPublishTask {
});
// 上传名单
log.info("任务导入客户名单......");
ImportTaskDto importTaskDto = new ImportTaskDto();
importTaskDto.setTaskId(taskId);
importTaskDto.setSecretType(2);
importTaskDto.setCustomerInfoList(customerInfoList);
aiobService.importTask(importTaskDto);
// 开启任务
aiobService.updateTaskStatus(taskId, 2);
List<ImportTaskVo> importTaskList = aiobService.importTask(importTaskDto);
String finalTaskId = taskId;
importTaskList.forEach(importTaskVo -> {
// 名单导入成功后sign_patient_manage_route_node表中设置taskId
if (importTaskVo.getStatus()) {
SignPatientManageRouteNode node = new SignPatientManageRouteNode();
node.setTaskIdExt(finalTaskId);
node.setId(Long.valueOf(importTaskVo.getExtJson()));
signPatientManageRouteNodeMapper.updateSignPatientManageRouteNode(node);
}
});
}
}
log.info("百度智能外呼创建任务定时任务执行完成......");
}
/**
* @description 删除话术任务记录表信息每天晚上执行一次
* @Author haown
* @Date 2024-9-5 13:54
*/
public void deleteScriptTask() {
log.info("删除话术任务记录表信息任务开始执行......");
scriptInfoTaskInfoMapper.deleteScriptInfoTaskInfo();
log.info("删除话术任务记录表信息任务执行完成......");
}
}