曜智智能外呼对接。

This commit is contained in:
haown 2025-12-23 09:47:50 +08:00
parent a970034721
commit 0073751675
9 changed files with 786 additions and 32 deletions

View File

@ -7,10 +7,10 @@ spring:
# 主库数据源
master:
# url: jdbc:mysql://192.168.16.64:3306/post-discharge?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
url: jdbc:mysql://127.0.0.1:3306/post-discharge?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
url: jdbc:mysql://8.131.93.145:54081/post-discharge?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
# url: jdbc:mysql://182.92.166.109:8000/post-discharge?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: Xinyilu@1qaz!@#$1234
password: 1qaz!@#$
# 从库数据源
slave:
# 从数据源开关/默认关闭
@ -21,9 +21,9 @@ spring:
hkhis:
# 从数据源开关/默认关闭
enabled: true
url: jdbc:mysql://127.0.0.1:3306/post-discharge?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
url: jdbc:mysql://8.131.93.145:54081/post-discharge?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
username: root
password: sa123456
password: 1qaz!@#$
driverClassName: com.mysql.cj.jdbc.Driver
# 初始连接数
initialSize: 5

View File

@ -87,7 +87,7 @@ spring:
# 数据库索引
database: 6
# 密码
password:
password: foobared
# 连接超时时间
timeout: 10s
lettuce:
@ -292,11 +292,18 @@ aiob:
accessKey: 9a61c68abf134ab9823e39f61f2c2f72
secretKey: 4287bfa1d5a34c229aacb5e056c94682
# 任务执行回调地址--测试
callBackUrl: http://182.92.166.109:9707/api/taskCallBack
# callBackUrl: http://182.92.166.109:9707/api/taskCallBack
# callBackUrl: http://182.92.166.109:19090/api/taskCallBack
# callBackUrl: http://101.200.89.70:19090/api/taskCallBack
# callBackUrl: http://8.131.93.145:54011/api/taskCallBack
callBackUrl: http://8.131.93.145:54011/api/taskCallBack
# 曜智智能外呼接口
yzaiobs:
# 请求地址
url: http://47.109.194.76:8094/AIOBS
userId: 00447a7b-3174-4bc5-b917-8b72b29bc920
routeNum: 1
callPhone: 1234
xinyilu-database:
# 公共机构ID新医路用于宣教库公共库查询
id: 46

View File

@ -0,0 +1,99 @@
package com.xinelu.manage.dto.aiob;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
/**
* @description: 曜智创建任务传输对象
* @author: haown
* @create: 2025-12-17 16:39
**/
@Data
public class CreateDutyDto {
/**
* 推送批次唯一标识
*/
private String accountId;
/**
* 任务名称
*/
private String dutyName;
/**
* 任务类型名称
*/
private String dutyType;
/**
* 外呼场景id话术id
*/
private Integer dutySceneId;
/**
* 外呼时间段格式按:["09:00~11:35","15:55~23:30"]
*/
private String outboundPeriods;
/**
* 外拨开始时间
*/
private String startDate;
/**
* 外呼终止时间
*/
private String endDate;
/**
* 重复拨打设置任务是否需要重呼并且指定重呼次数
* (0-,1-重复1次,2-重复2次,3-重复3次,4-重复4次)
*/
private Integer duplication;
/**
* 重复拨打时间间隔,单位为分钟
*/
private Integer period;
/**
* 重呼策略{"hangState":"","state":"","intention":""}
*/
private JSONObject repStrategy;
/**
* 数据权限字段
*/
private String roleId;
/**
* 是否回传外呼结果数据0:不回传1回传
*/
private Integer noticeSwitch;
/**
* 用户id
*/
private String userId;
/**
* 分配路数
*/
private Integer routeNum;
/**
* 主叫号码
*/
private String callPhone;
/**
* 手机号是否去重默认true
*/
private Boolean deduplicationSwitch;
/**
* 场景中设置的变量数组
*/
private JSONArray dataArr;
}

View File

@ -0,0 +1,92 @@
package com.xinelu.manage.dto.aiob;
import lombok.Data;
/**
* @description: 外呼结果回调传输data
* @author: haown
* @create: 2025-12-18 17:19
**/
@Data
public class DutyCallbackDataDto {
/**
* 任务主键
*/
private String custId;
/**
* 患者姓名
*/
private String name;
/**
* 拨打次数
*/
private Integer callNumber;
/**
* 电话是否拨打完毕01
*/
private Integer isEnd;
/**
* 外呼是否成功发起,01,成功状态包括通话成功占线无法接通接听挂断未接听超时关机等失败指未呼出
*/
private Integer isCall;
/**
* 呼叫时间yyy-mm-dd hh:mm:ss
*/
private String callTime;
/**
* 是否接听01
*/
private Integer isAnswer;
/**
* 未接听原因
*/
private String noAnswerReason;
/**
* 接听时间
*/
private String answerTime;
/**
* 通话结束时间
*/
private String endTime;
/**
* 通话时长
*/
private Integer callTimeLength;
/**
* 交互过程中命中的意向标签,用英文,隔开
*/
private String callResultType;
/**
* 通话录音链接
*/
private String mediaPath;
/**
* 录音转文本
*/
private String interactions;
/**
* 被叫号码
*/
private String phoneNumber;
/**
* 每通电话唯一标识
*/
private String callid;
}

View File

@ -0,0 +1,43 @@
package com.xinelu.manage.dto.aiob;
import com.alibaba.fastjson2.JSONArray;
import lombok.Data;
/**
* @description: 曜智任务回调传输对象
* @author: haown
* @create: 2025-12-18 16:31
**/
@Data
public class DutyCallbackDto {
/**
* 推送批次唯一标识
*/
private String accountId;
/**
* 外拨场景id话术id
*/
private String dutySceneId;
/**
* 数据权限字段
*/
private String roleId;
/**
* 主叫号码
*/
private String phoneNum;
/**
* 任务执行时间
*/
private String dutyStartTime;
/**
* 回传的数据
*/
private JSONArray data;
}

View File

@ -1,7 +1,10 @@
package com.xinelu.manage.service.aiob;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
import com.xinelu.manage.domain.signpatientmanageroutenode.SignPatientManageRouteNode;
import com.xinelu.manage.dto.aiob.ActualTimeTaskDto;
import com.xinelu.manage.dto.aiob.CreateTaskDto;
import com.xinelu.manage.dto.aiob.ImportTaskDto;
@ -89,4 +92,10 @@ public interface IAIOBService {
* @Date 2024-11-8 13:49
*/
String getPhoneDialRecord(String ccUuid);
void sendSms(Long patientId, SignPatientManageRouteNode signPatientManageRouteNode) throws ClientException;
void redialInfoSave(SignPatientManageRouteNode signPatientManageRouteNode, PatientVisitRecord patientVisitRecord);
void parseQuestionInfo(JSONArray records, SignPatientManageRouteNode node, Long patientInfoId, Long taskExecuteRecordId);
}

View File

@ -5,12 +5,21 @@ import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.sun.media.jfxmedia.logging.Logger;
import com.xinelu.common.config.AliYunSmsTwoConfig;
import com.xinelu.common.config.SystemBusinessConfig;
import com.xinelu.common.constant.*;
import com.xinelu.common.constant.AiobTaskTypeContant;
import com.xinelu.common.constant.Constants;
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.*;
import com.xinelu.common.enums.ContentedAndRemarkableFlagEnum;
import com.xinelu.common.enums.ErrorStatusEnum;
import com.xinelu.common.enums.NodeExecuteResultStatusEnum;
import com.xinelu.common.enums.NodeExecuteStatusEnum;
import com.xinelu.common.enums.PhoneDialMethodEnum;
import com.xinelu.common.enums.PhoneRedialTimesEnum;
import com.xinelu.common.enums.TaskNodeTypeEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.StringUtils;
import com.xinelu.manage.domain.patientinfo.PatientInfo;
@ -28,7 +37,12 @@ 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.aiob.*;
import com.xinelu.manage.dto.aiob.ActualTimeTaskDto;
import com.xinelu.manage.dto.aiob.AiobRecord;
import com.xinelu.manage.dto.aiob.CreateTaskDto;
import com.xinelu.manage.dto.aiob.CustomerInfoDto;
import com.xinelu.manage.dto.aiob.ImportTaskDto;
import com.xinelu.manage.dto.aiob.TaskCallbackDataDto;
import com.xinelu.manage.dto.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
import com.xinelu.manage.dto.smssend.SmsInfoDTO;
import com.xinelu.manage.mapper.labelfieldcontent.LabelFieldContentMapper;
@ -55,29 +69,41 @@ import com.xinelu.manage.service.signpatientmanageroutenode.ISignPatientManageRo
import com.xinelu.manage.vo.aiob.ImportTaskVo;
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
import com.xinelu.manage.vo.questionsubject.QuestionSubjectVO;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
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;
import org.springframework.http.HttpMethod;
import org.springframework.http.*;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* @description: 百度客悦·智能外呼平台Service实现
* @author: haown
@ -356,17 +382,13 @@ public class AIOBServiceImpl implements IAIOBService {
|| phoneDialRecordList.size() + 1 < PhoneRedialTimesEnum.getValueByInfo(redialTimes).getValue()) {
// 重拨
needRedial = true;
}
//如果不需要重拨则设置完成时间,问卷提交失败
else
{
} else { //如果不需要重拨则设置完成时间,问卷提交失败
// 问卷设置任务完成时间
if (StringUtils.equals(TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo(), signPatientManageRouteNode.getTaskNodeType())) {
signPatientManageRouteNode.setNodeFinishDate(LocalDateTime.now());
signPatientManageRouteNode.setNodeFinishStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
}
}
}
} else {
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
@ -503,7 +525,8 @@ public class AIOBServiceImpl implements IAIOBService {
return obj.getOrDefault("downloadUrl", null).toString();
}
private void sendSms(Long patientId, SignPatientManageRouteNode signPatientManageRouteNode) throws ClientException {
@Override
public void sendSms(Long patientId, SignPatientManageRouteNode signPatientManageRouteNode) throws ClientException {
TextMessage textMessage = textMessageMapper.selectTextMessageById(signPatientManageRouteNode.getPhoneMessageTemplateId());
if (ObjectUtils.isNotEmpty(textMessage)) {
// 发送短信
@ -568,7 +591,8 @@ public class AIOBServiceImpl implements IAIOBService {
* @Author haown
* @Date 2024-9-6 14:30
*/
private void parseQuestionInfo(JSONArray records, SignPatientManageRouteNode node, Long patientInfoId, Long taskExecuteRecordId) {
@Override
public void parseQuestionInfo(JSONArray records, SignPatientManageRouteNode node, Long patientInfoId, Long taskExecuteRecordId) {
List<AiobRecord> aiobRecords = records.toList(AiobRecord.class);
List<AiobRecord> speechList = aiobRecords.stream().filter(record -> StringUtils.equals("speech", record.getRole()) && !StringUtils.equals("抱歉,我不太理解您的意思", record.getContextText()))
.collect(Collectors.toMap(AiobRecord::getContextText, p -> p, (p1, p2) -> p2))
@ -757,7 +781,8 @@ public class AIOBServiceImpl implements IAIOBService {
* @Author haown
* @Date 2024-9-24 15:08
*/
private void redialInfoSave(SignPatientManageRouteNode signPatientManageRouteNode, PatientVisitRecord patientVisitRecord) {
@Override
public void redialInfoSave(SignPatientManageRouteNode signPatientManageRouteNode, PatientVisitRecord patientVisitRecord) {
ScriptInfoTaskInfo scriptInfoTaskInfo = new ScriptInfoTaskInfo();
scriptInfoTaskInfo.setScriptInfoId(signPatientManageRouteNode.getScriptInfoId());
scriptInfoTaskInfo.setRobotId(signPatientManageRouteNode.getRobotPublishId());

View File

@ -0,0 +1,35 @@
package com.xinelu.manage.service.yzaiobs;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.manage.dto.aiob.CreateDutyDto;
import com.xinelu.manage.dto.aiob.DutyCallbackDto;
/**
* 曜智·智能外呼平台Service接口
*
* @author: haown
* @create: 2025-12-17 16:19
*/
public interface IYZAIOBSService {
/**
* @description 创建任务
* @Param 曜智创建任务传输对象
* @return null
* @Author haown
* @Date 2025-12-17 16:27
*/
JSONObject createDuty(CreateDutyDto createDutyDto);
/**
* @description 任务执行回调方法
* @param callbackDto 任务执行完毕后回调传输对象
* @return JSONObject
* @Author haown
* @Date 2024-9-2 14:20
*/
JSONObject taskCallBack(DutyCallbackDto callbackDto) throws ClientException;
}

View File

@ -0,0 +1,444 @@
package com.xinelu.manage.service.yzaiobs.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.xinelu.common.constant.PhoneMessageRemindConstants;
import com.xinelu.common.constant.TaskCreateTypeConstant;
import com.xinelu.common.constant.TaskStatisticsTypeConstants;
import com.xinelu.common.enums.ContentedAndRemarkableFlagEnum;
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.enums.TaskNodeTypeEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.StringUtils;
import com.xinelu.manage.domain.patientinfo.PatientInfo;
import com.xinelu.manage.domain.patientquestionoptionresult.PatientQuestionOptionResult;
import com.xinelu.manage.domain.patientquestionsubjectresult.PatientQuestionSubjectResult;
import com.xinelu.manage.domain.patientquestionsubmitresult.PatientQuestionSubmitResult;
import com.xinelu.manage.domain.patienttaskexecuterecord.PatientTaskExecuteRecord;
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
import com.xinelu.manage.domain.phonedialrecord.PhoneDialRecord;
import com.xinelu.manage.domain.questioninfo.QuestionInfo;
import com.xinelu.manage.domain.questionsubjectoption.QuestionSubjectOption;
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.dto.aiob.AiobRecord;
import com.xinelu.manage.dto.aiob.CreateDutyDto;
import com.xinelu.manage.dto.aiob.DutyCallbackDataDto;
import com.xinelu.manage.dto.aiob.DutyCallbackDto;
import com.xinelu.manage.mapper.patienttaskexecuterecord.PatientTaskExecuteRecordMapper;
import com.xinelu.manage.mapper.patientvisitrecord.PatientVisitRecordMapper;
import com.xinelu.manage.mapper.phonedialrecord.PhoneDialRecordMapper;
import com.xinelu.manage.mapper.scriptinfotaskinfo.ScriptInfoTaskInfoMapper;
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.service.aiob.IAIOBService;
import com.xinelu.manage.service.patienttaskstatistics.IPatientTaskStatisticsService;
import com.xinelu.manage.service.yzaiobs.IYZAIOBSService;
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
import com.xinelu.manage.vo.questionsubject.QuestionSubjectVO;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
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.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
/**
* @description:
* @author: haown
* @create: 2025-12-17 17:18
**/
@Service
public class YZAIOBSServiceImpl implements IYZAIOBSService {
@Value("${yzaiobs.url}")
private String url;
@Value("${yzaiobs.userId}")
private String userId;
@Value("${yzaiobs.routeNum}")
private Integer routeNum;
@Value("${yzaiobs.callPhone}")
private String callPhone;
@Resource
private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
@Resource
private PhoneDialRecordMapper phoneDialRecordMapper;
@Resource
private ScriptInfoTaskInfoMapper scriptInfoTaskInfoMapper;
@Resource
private PatientVisitRecordMapper patientVisitRecordMapper;
@Resource
private SignPatientRecordMapper signPatientRecordMapper;
@Resource
private SignPatientManageRouteMapper signPatientManageRouteMapper;
@Resource
private IAIOBService iaiobService;
@Resource
private PatientTaskExecuteRecordMapper patientTaskExecuteRecordMapper;
@Resource
private IPatientTaskStatisticsService patientTaskStatisticsService;
@Override public JSONObject createDuty(CreateDutyDto createDutyDto) {
createDutyDto.setUserId(userId);
createDutyDto.setRouteNum(routeNum);
createDutyDto.setCallPhone(callPhone);
HttpEntity<JSONObject> requestEntity = new HttpEntity<>((JSONObject) JSON.toJSON(createDutyDto));
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.exchange(url + "/createDuty", HttpMethod.POST, requestEntity, String.class);
JSONObject object = JSON.parseObject(responseEntity.getBody());
/*{
"flag": true,
"message": "任务名已存在!!!",
"ret": 0,
"success": false // 任务创建结果true表示创建成功false表示创建失败
}*/
/*{
"flag": true,
"message": "入库成功",
"ret": 0, // 0表示成功非0表示失败
"success": true, // 任务创建结果true表示创建成功false表示创建失败
"value": {
"166": [ // 已创建的任务id
{
"id": 1045, // 任务资源id
"phoneNumber": "18156017972", // 用户手机号
"downLoadState": false // 音频是否下载完成
}
]
}
}*/
if (object == null || object.getBoolean("success") == null || !object.getBoolean("success")) {
throw new ServiceException("创建任务失败," + object.getString("message"));
}
JSONObject data = object.getJSONObject("value");
Set<String> taskIds = data.keySet();
Iterator<String> iterator = taskIds.iterator();
String taskId = iterator.next();
return data;
}
@Override public JSONObject taskCallBack(DutyCallbackDto callbackDto) throws ClientException {
// 根据第三方任务批次id查询任务列表
String accountId = callbackDto.getAccountId();
// 从data中获取任务id
JSONArray JSONArr = callbackDto.getData();
if (!CollectionUtils.isEmpty(JSONArr)) {
for (int i = 0; i < JSONArr.size(); i++) {
JSONObject jsonObject = (JSONObject) JSONArr.get(i);
DutyCallbackDataDto dutyCallbackDataDto = JSON.parseObject(jsonObject.toJSONString(), DutyCallbackDataDto.class);
// 是否发送短信标识
boolean needSendSms = false;
// 是否重拨
boolean needRedial = false;
// 根据id查询任务
SignPatientManageRouteNode signPatientManageRouteNode = signPatientManageRouteNodeMapper.selectSignPatientManageRouteNodeById(Long.valueOf(dutyCallbackDataDto.getCustId()));
if (ObjectUtils.isNotEmpty(signPatientManageRouteNode)) {
// 标记任务执行状态
signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.EXECUTED.getInfo());
//接通状态1-已接通 0-未接通
//如果未接通
if (dutyCallbackDataDto.getIsAnswer() != null && dutyCallbackDataDto.getIsAnswer() == 0) {
// 设置电话拨通情况
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
// 电话短信提醒
if (StringUtils.equals(PhoneMessageRemindConstants.NOT_CONNECTED_SEND_MESSAGE, signPatientManageRouteNode.getPhoneMessageRemind())) {
// 发送短信
needSendSms = true;
}
// 实时任务设置电话重拨
// 查询拨打次数
PhoneDialRecord phoneDialRecordQuery = new PhoneDialRecord();
phoneDialRecordQuery.setManageRouteNodeId(signPatientManageRouteNode.getId());
List<PhoneDialRecord> phoneDialRecordList = phoneDialRecordMapper.selectPhoneDialRecordList(phoneDialRecordQuery);
String redialTimes = StringUtils.isEmpty(signPatientManageRouteNode.getPhoneRedialTimes())?"NOT_REPLAY":signPatientManageRouteNode.getPhoneRedialTimes();
if ((org.apache.commons.collections4.CollectionUtils.isEmpty(phoneDialRecordList) && PhoneRedialTimesEnum.getValueByInfo(redialTimes).getValue() > 0)
|| phoneDialRecordList.size() + 1 < PhoneRedialTimesEnum.getValueByInfo(redialTimes).getValue()) {
// 重拨
needRedial = true;
} else { //如果不需要重拨则设置完成时间,问卷提交失败
// 问卷设置任务完成时间
if (StringUtils.equals(TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo(), signPatientManageRouteNode.getTaskNodeType())) {
signPatientManageRouteNode.setNodeFinishDate(LocalDateTime.now());
signPatientManageRouteNode.setNodeFinishStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
}
}
} else {
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
// 问卷设置任务完成时间,问卷提交成功
if (StringUtils.equals(TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo(), signPatientManageRouteNode.getTaskNodeType())) {
signPatientManageRouteNode.setNodeFinishDate(LocalDateTime.now());
signPatientManageRouteNode.setNodeFinishStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
}
if (StringUtils.equals(PhoneMessageRemindConstants.CONNECTED_SEND_MESSAGE, signPatientManageRouteNode.getPhoneMessageRemind())) {
// 发送短信
needSendSms = true;
}
// 记录通话详情 放到外面执行
// signPatientManageRouteNode.setPhoneResultJson(com.alibaba.fastjson.JSON.toJSONString(data, SerializerFeature.WriteMapNullValue));
}
signPatientManageRouteNode.setPhoneResultJson(callbackDto.toString());
signPatientManageRouteNodeMapper.updateSignPatientManageRouteNode(signPatientManageRouteNode);
// 重拨表任务执行状态修改
scriptInfoTaskInfoMapper.updateExecuteStatusByNodeId(signPatientManageRouteNode.getId());
// 任务执行记录
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) {
//System.out.println("发送短信-------------------------------------------");
iaiobService.sendSms(signPatientManageRoute.getPatientId(), signPatientManageRouteNode);
}
// 重拨
if (needRedial) {
if (ObjectUtils.isNotEmpty(signPatientRecord)) {
PatientVisitRecord patientVisitRecord = patientVisitRecordMapper.selectPatientVisitRecordById(signPatientRecord.getPatientVisitRecordId());
iaiobService.redialInfoSave(signPatientManageRouteNode, patientVisitRecord);
} else {
iaiobService.redialInfoSave(signPatientManageRouteNode, null);
}
}
}
// 增加任务执行记录
patientTaskExecuteRecord.setManageRouteNodeId(signPatientManageRouteNode.getId());
patientTaskExecuteRecord.setManageRouteNodeName(signPatientManageRouteNode.getRouteNodeName());
patientTaskExecuteRecord.setExecuteResult(dutyCallbackDataDto.getNoAnswerReason());
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(callbackDto.getPhoneNum());
phoneDialRecord.setDialTime(LocalDateTime.now());
phoneDialRecord.setPhoneTemplateId(signPatientManageRouteNode.getScriptInfoId() + "");
phoneDialRecord.setPhoneDialMethod(signPatientManageRouteNode.getPhoneDialMethod());
phoneDialRecord.setErrorCode(dutyCallbackDataDto.getIsAnswer() == 0 ? 1L : 0);
phoneDialRecord.setErrorStatus(dutyCallbackDataDto.getIsAnswer() == 0 ? ErrorStatusEnum.fail.getValue() : ErrorStatusEnum.success.getValue());
phoneDialRecord.setCreateTime(LocalDateTime.now());
phoneDialRecord.setCtUuid(dutyCallbackDataDto.getCallid());
//phoneDialRecord.setPhoneDialRecordVideo(getPhoneDialRecord(data.getContactUUID()));
phoneDialRecordMapper.insertPhoneDialRecord(phoneDialRecord);
// 修改任务统计表数据
if (patientTaskExecuteRecordMapper.insertPatientTaskExecuteRecord(patientTaskExecuteRecord) > 0) {
// 任务统计表修改
patientTaskStatisticsService.updateNum(signPatientManageRoute.getPatientId(), TaskStatisticsTypeConstants.TASK_EXECUTE_NUM, 1);
}
//接通状态1-已接通
if (dutyCallbackDataDto.getIsAnswer() != null && dutyCallbackDataDto.getIsAnswer() == 1) {
// 问卷记录保存
if (StringUtils.equals(signPatientManageRouteNode.getTaskNodeType(), TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo())) {
iaiobService.parseQuestionInfo(data.getRecord(), signPatientManageRouteNode, signPatientManageRoute.getPatientId(), patientTaskExecuteRecord.getId());
}
}
}
}
}
return null;
}
private void parseQuestionInfo(String interactions, SignPatientManageRouteNode signPatientManageRouteNode, Long patientInfoId, String taskExecuteRecordId) {
List<AiobRecord> aiobRecords = records.toList(AiobRecord.class);
List<AiobRecord> speechList = aiobRecords.stream().filter(record -> StringUtils.equals("speech", record.getRole()) && !StringUtils.equals("抱歉,我不太理解您的意思", record.getContextText()))
.collect(Collectors.toMap(AiobRecord::getContextText, p -> p, (p1, p2) -> p2))
.values()
.stream()
.sorted(Comparator.comparing(AiobRecord::getTimestamp))
.collect(Collectors.toList());
speechList.forEach(s->{
if(StringUtils.isNull(s.getIntent())) s.setIntent("");
});
// 查询患者画像信息
List<LabelFieldInfoContentVo> labelFieldContentList = labelFieldContentMapper.selectByPatientId(patientInfoId);
Map<String, String> contextMap = speechList.stream().collect(Collectors.toMap(AiobRecord::getContextText, AiobRecord::getIntent));
PatientInfo patientInfo = patientInfoMapper.selectPatientInfoById(patientInfoId);
QuestionInfo questionInfo = questionInfoMapper.selectQuestionInfoById(node.getQuestionInfoId());
// 1保存patient_question_submit_result
PatientQuestionSubmitResult patientQuestionSubmitResult = new PatientQuestionSubmitResult();
patientQuestionSubmitResult.setTaskExecuteRecordId(taskExecuteRecordId);
patientQuestionSubmitResult.setPatientName(patientInfo.getPatientName());
patientQuestionSubmitResult.setPatientId(patientInfoId);
patientQuestionSubmitResult.setManageRouteId(node.getManageRouteId());
patientQuestionSubmitResult.setManageRouteName(node.getManageRouteName());
patientQuestionSubmitResult.setManageRouteNodeId(node.getId());
patientQuestionSubmitResult.setManageRouteNodeName(node.getRouteNodeName());
patientQuestionSubmitResult.setQuestionInfoId(questionInfo.getId());
patientQuestionSubmitResult.setDepartmentId(questionInfo.getDepartmentId());
patientQuestionSubmitResult.setDepartmentName(questionInfo.getDepartmentName());
patientQuestionSubmitResult.setDiseaseTypeId(questionInfo.getDiseaseTypeId());
patientQuestionSubmitResult.setDiseaseTypeName(questionInfo.getDiseaseTypeName());
patientQuestionSubmitResult.setQuestionnaireName(questionInfo.getQuestionnaireName());
patientQuestionSubmitResult.setQuestionnaireDescription(questionInfo.getQuestionnaireDescription());
patientQuestionSubmitResult.setAnsweringMethod(questionInfo.getAnsweringMethod());
patientQuestionSubmitResult.setQuestionnaireId(questionInfo.getQuestionnaireId());
patientQuestionSubmitResult.setQuestionCount(questionInfo.getQuestionCount());
patientQuestionSubmitResult.setQuestionnaireTotalScore(questionInfo.getQuestionnaireTotalScore());
patientQuestionSubmitResult.setResidentId(patientInfo.getResidentId());
patientQuestionSubmitResult.setCreateTime(LocalDateTime.now());
questionSubmitResultMapper.insertPatientQuestionSubmitResult(patientQuestionSubmitResult);
// 2保存patient_question_subject_result
final BigDecimal[] totalScore = { BigDecimal.ZERO };
List<QuestionSubjectVO> questionSubjectList = questionSubjectMapper.selectQuestionSubjectBy(node.getQuestionInfoId());
questionSubjectList.forEach(questionSubjectVO -> {
// 判断问题中有无变量有变量替换变量
String questionNameAlias = replaceQuestionName(questionSubjectVO.getQuestionNameAlias(), labelFieldContentList);
// 根据通话记录筛查是否询问该问题
boolean hasQuestion = false;
String aiobQuestionName = "";
for (String questionContent : contextMap.keySet()) {
if (questionContent.replaceAll("\\p{P}", "").contains(questionNameAlias.replaceAll("\\p{P}", ""))) {
hasQuestion = true;
aiobQuestionName = questionContent;
break;
}
}
if (hasQuestion) {
String finalAiobQuestionName = aiobQuestionName;
AiobRecord nextRecord = getNextQuestion(speechList, finalAiobQuestionName);
PatientQuestionSubjectResult patientQuestionSubjectResult = new PatientQuestionSubjectResult();
BeanUtils.copyProperties(questionSubjectVO, patientQuestionSubjectResult);
patientQuestionSubjectResult.setId(null);
patientQuestionSubjectResult.setQuestionSubmitResultId(patientQuestionSubmitResult.getId());
patientQuestionSubjectResult.setCreateTime(LocalDateTime.now());
//不管是否是 填空题 写入回答 文本
patientQuestionSubjectResult.setFillBlanksAnswer(nextRecord.getContent());
patientQuestionSubjectResult.setQuestionSubjectId(questionSubjectVO.getId());
patientQuestionSubjectResultMapper.insertPatientQuestionSubjectResult(patientQuestionSubjectResult);
// 3保存patient_question_option_result
QuestionSubjectOption questionSubjectOptionQuery = new QuestionSubjectOption();
questionSubjectOptionQuery.setQuestionnaireSubjectId(questionSubjectVO.getId());
List<QuestionSubjectOption> questionSubjectOptions = questionSubjectOptionMapper.selectQuestionSubjectOptionList(questionSubjectOptionQuery);
List<PatientQuestionOptionResult> patientQuestionOptionResults = new ArrayList<>();
questionSubjectOptions.forEach(questionSubjectOption -> {
PatientQuestionOptionResult patientQuestionOptionResult = new PatientQuestionOptionResult();
BeanUtils.copyProperties(questionSubjectOption, patientQuestionOptionResult);
// 设置是否选中, 通过通话记录中下一个问题的intent字段查询QuestionSubjectOption
List<String> intents = Arrays.asList(questionSubjectOption.getIntent().split("\\|"));
if (ObjectUtils.isNotEmpty(nextRecord) && intents.contains(nextRecord.getIntent())) {
patientQuestionOptionResult.setOptionChooseSign(0);
} else {
patientQuestionOptionResult.setOptionChooseSign(1);
}
patientQuestionOptionResult.setId(null);
patientQuestionOptionResult.setCreateTime(LocalDateTime.now());
patientQuestionOptionResult.setQuestionSubjectResultId(patientQuestionSubjectResult.getId());
patientQuestionOptionResult.setQuestionSubjectOptionId(questionSubjectOption.getId());
patientQuestionOptionResults.add(patientQuestionOptionResult);
});
//判断问卷 满意项与异常项
patientQuestionSubmitResult.setRemarkableFlag(ContentedAndRemarkableFlagEnum.ROUTINE.getInfo());
patientQuestionSubmitResult.setContentedFlag(ContentedAndRemarkableFlagEnum.CONTENTED.getInfo());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(patientQuestionOptionResults)) {
List<PatientQuestionOptionResult> remarkableFlag = patientQuestionOptionResults.stream().filter(Objects::nonNull)
.filter(item -> org.apache.commons.lang3.StringUtils.isNotBlank(item.getRemarkableFlag())
&& Objects.nonNull(item.getOptionChooseSign()) && item.getOptionChooseSign().equals(0)
&& ContentedAndRemarkableFlagEnum.REMARKABLE.getInfo().equals(item.getRemarkableFlag()))
.collect(Collectors.toList());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(remarkableFlag)) {
patientQuestionSubmitResult.setRemarkableFlag(ContentedAndRemarkableFlagEnum.REMARKABLE.getInfo());
}
List<PatientQuestionOptionResult> contentedFlag = patientQuestionOptionResults.stream().filter(Objects::nonNull).filter(item -> org.apache.commons.lang3.StringUtils.isNotBlank(item.getContentedFlag()) && Objects.nonNull(item.getOptionChooseSign()) && item.getOptionChooseSign().equals(0) && ContentedAndRemarkableFlagEnum.DISCONTENTED.getInfo().equals(item.getRemarkableFlag())).collect(Collectors.toList());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(contentedFlag)) {
patientQuestionSubmitResult.setContentedFlag(ContentedAndRemarkableFlagEnum.DISCONTENTED.getInfo());
}
}
questionSubmitResultMapper.updatePatientQuestionSubmitResult(patientQuestionSubmitResult);
if(patientQuestionOptionResults.size()>0) {
patientQuestionOptionResultMapper.saveQuestionOptionList(patientQuestionOptionResults);
}
totalScore[0] = totalScore[0].add(questionSubjectVO.getQuestionScore() == null ? BigDecimal.ZERO : questionSubjectVO.getQuestionScore());
} else {
// 没问到问卷中的问题则保存空问题+空选项
PatientQuestionSubjectResult patientQuestionSubjectResult = new PatientQuestionSubjectResult();
BeanUtils.copyProperties(questionSubjectVO, patientQuestionSubjectResult);
patientQuestionSubjectResult.setId(null);
patientQuestionSubjectResult.setQuestionSubmitResultId(patientQuestionSubmitResult.getId());
patientQuestionSubjectResult.setCreateTime(LocalDateTime.now());
patientQuestionSubjectResultMapper.insertPatientQuestionSubjectResult(patientQuestionSubjectResult);
// 3保存空选项
QuestionSubjectOption questionSubjectOptionQuery = new QuestionSubjectOption();
questionSubjectOptionQuery.setQuestionnaireSubjectId(questionSubjectVO.getId());
List<QuestionSubjectOption> questionSubjectOptions = questionSubjectOptionMapper.selectQuestionSubjectOptionList(questionSubjectOptionQuery);
List<PatientQuestionOptionResult> patientQuestionOptionResults = new ArrayList<>();
questionSubjectOptions.forEach(questionSubjectOption -> {
PatientQuestionOptionResult patientQuestionOptionResult = new PatientQuestionOptionResult();
BeanUtils.copyProperties(questionSubjectOption, patientQuestionOptionResult);
patientQuestionOptionResult.setOptionChooseSign(1);
patientQuestionOptionResult.setId(null);
patientQuestionOptionResult.setCreateTime(LocalDateTime.now());
patientQuestionOptionResult.setQuestionSubjectResultId(patientQuestionSubjectResult.getId());
patientQuestionOptionResults.add(patientQuestionOptionResult);
});
if(patientQuestionOptionResults.size()>0) {
patientQuestionOptionResultMapper.saveQuestionOptionList(patientQuestionOptionResults);
}
totalScore[0] = totalScore[0].add(BigDecimal.ZERO);
}
});
// 4更新总得分
patientQuestionSubmitResult.setTotalScore(totalScore[0]);
questionSubmitResultMapper.updatePatientQuestionSubmitResult(patientQuestionSubmitResult);
}
}