曜智智能外呼对接。
This commit is contained in:
parent
a970034721
commit
0073751675
@ -7,10 +7,10 @@ spring:
|
|||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
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://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
|
# 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
|
username: root
|
||||||
password: Xinyilu@1qaz!@#$1234
|
password: 1qaz!@#$
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
# 从数据源开关/默认关闭
|
# 从数据源开关/默认关闭
|
||||||
@ -21,9 +21,9 @@ spring:
|
|||||||
hkhis:
|
hkhis:
|
||||||
# 从数据源开关/默认关闭
|
# 从数据源开关/默认关闭
|
||||||
enabled: true
|
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
|
username: root
|
||||||
password: sa123456
|
password: 1qaz!@#$
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
# 初始连接数
|
# 初始连接数
|
||||||
initialSize: 5
|
initialSize: 5
|
||||||
|
|||||||
@ -87,7 +87,7 @@ spring:
|
|||||||
# 数据库索引
|
# 数据库索引
|
||||||
database: 6
|
database: 6
|
||||||
# 密码
|
# 密码
|
||||||
password:
|
password: foobared
|
||||||
# 连接超时时间
|
# 连接超时时间
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
lettuce:
|
lettuce:
|
||||||
@ -292,11 +292,18 @@ aiob:
|
|||||||
accessKey: 9a61c68abf134ab9823e39f61f2c2f72
|
accessKey: 9a61c68abf134ab9823e39f61f2c2f72
|
||||||
secretKey: 4287bfa1d5a34c229aacb5e056c94682
|
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://182.92.166.109:19090/api/taskCallBack
|
||||||
# callBackUrl: http://101.200.89.70: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:
|
xinyilu-database:
|
||||||
# 公共机构ID(新医路,用于宣教库公共库查询)
|
# 公共机构ID(新医路,用于宣教库公共库查询)
|
||||||
id: 46
|
id: 46
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电话是否拨打完毕0:否;1:是
|
||||||
|
*/
|
||||||
|
private Integer isEnd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外呼是否成功发起,0:否;1:是,成功状态包括通话成功、占线、无法接通、接听挂断、未接听、超时、关机等;失败指未呼出。
|
||||||
|
*/
|
||||||
|
private Integer isCall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 呼叫时间yyy-mm-dd hh:mm:ss
|
||||||
|
*/
|
||||||
|
private String callTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否接听,0:否;1:是
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
package com.xinelu.manage.service.aiob;
|
package com.xinelu.manage.service.aiob;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.aliyuncs.exceptions.ClientException;
|
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.ActualTimeTaskDto;
|
||||||
import com.xinelu.manage.dto.aiob.CreateTaskDto;
|
import com.xinelu.manage.dto.aiob.CreateTaskDto;
|
||||||
import com.xinelu.manage.dto.aiob.ImportTaskDto;
|
import com.xinelu.manage.dto.aiob.ImportTaskDto;
|
||||||
@ -89,4 +92,10 @@ public interface IAIOBService {
|
|||||||
* @Date 2024-11-8 13:49
|
* @Date 2024-11-8 13:49
|
||||||
*/
|
*/
|
||||||
String getPhoneDialRecord(String ccUuid);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,21 @@ import com.alibaba.fastjson2.JSON;
|
|||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.aliyuncs.exceptions.ClientException;
|
import com.aliyuncs.exceptions.ClientException;
|
||||||
import com.sun.media.jfxmedia.logging.Logger;
|
|
||||||
import com.xinelu.common.config.AliYunSmsTwoConfig;
|
import com.xinelu.common.config.AliYunSmsTwoConfig;
|
||||||
import com.xinelu.common.config.SystemBusinessConfig;
|
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.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.exception.ServiceException;
|
||||||
import com.xinelu.common.utils.StringUtils;
|
import com.xinelu.common.utils.StringUtils;
|
||||||
import com.xinelu.manage.domain.patientinfo.PatientInfo;
|
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.signpatientmanageroutenode.SignPatientManageRouteNode;
|
||||||
import com.xinelu.manage.domain.signpatientrecord.SignPatientRecord;
|
import com.xinelu.manage.domain.signpatientrecord.SignPatientRecord;
|
||||||
import com.xinelu.manage.domain.textmessage.TextMessage;
|
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.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
|
||||||
import com.xinelu.manage.dto.smssend.SmsInfoDTO;
|
import com.xinelu.manage.dto.smssend.SmsInfoDTO;
|
||||||
import com.xinelu.manage.mapper.labelfieldcontent.LabelFieldContentMapper;
|
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.aiob.ImportTaskVo;
|
||||||
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
|
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
|
||||||
import com.xinelu.manage.vo.questionsubject.QuestionSubjectVO;
|
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 lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
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.HttpMethod;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.client.RestTemplate;
|
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实现
|
* @description: 百度客悦·智能外呼平台Service实现
|
||||||
* @author: haown
|
* @author: haown
|
||||||
@ -356,17 +382,13 @@ public class AIOBServiceImpl implements IAIOBService {
|
|||||||
|| phoneDialRecordList.size() + 1 < PhoneRedialTimesEnum.getValueByInfo(redialTimes).getValue()) {
|
|| phoneDialRecordList.size() + 1 < PhoneRedialTimesEnum.getValueByInfo(redialTimes).getValue()) {
|
||||||
// 重拨
|
// 重拨
|
||||||
needRedial = true;
|
needRedial = true;
|
||||||
}
|
} else { //如果不需要重拨,则设置完成时间,问卷提交失败
|
||||||
//如果不需要重拨,则设置完成时间,问卷提交失败
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 问卷设置任务完成时间
|
// 问卷设置任务完成时间
|
||||||
if (StringUtils.equals(TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo(), signPatientManageRouteNode.getTaskNodeType())) {
|
if (StringUtils.equals(TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo(), signPatientManageRouteNode.getTaskNodeType())) {
|
||||||
signPatientManageRouteNode.setNodeFinishDate(LocalDateTime.now());
|
signPatientManageRouteNode.setNodeFinishDate(LocalDateTime.now());
|
||||||
signPatientManageRouteNode.setNodeFinishStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
|
signPatientManageRouteNode.setNodeFinishStatus(NodeExecuteResultStatusEnum.FAILURE.getInfo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
|
signPatientManageRouteNode.setPhoneNodeExecuteResultStatus(NodeExecuteResultStatusEnum.SUCCESS.getInfo());
|
||||||
@ -503,7 +525,8 @@ public class AIOBServiceImpl implements IAIOBService {
|
|||||||
return obj.getOrDefault("downloadUrl", null).toString();
|
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());
|
TextMessage textMessage = textMessageMapper.selectTextMessageById(signPatientManageRouteNode.getPhoneMessageTemplateId());
|
||||||
if (ObjectUtils.isNotEmpty(textMessage)) {
|
if (ObjectUtils.isNotEmpty(textMessage)) {
|
||||||
// 发送短信
|
// 发送短信
|
||||||
@ -568,7 +591,8 @@ public class AIOBServiceImpl implements IAIOBService {
|
|||||||
* @Author haown
|
* @Author haown
|
||||||
* @Date 2024-9-6 14:30
|
* @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> aiobRecords = records.toList(AiobRecord.class);
|
||||||
List<AiobRecord> speechList = aiobRecords.stream().filter(record -> StringUtils.equals("speech", record.getRole()) && !StringUtils.equals("抱歉,我不太理解您的意思", record.getContextText()))
|
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))
|
.collect(Collectors.toMap(AiobRecord::getContextText, p -> p, (p1, p2) -> p2))
|
||||||
@ -757,7 +781,8 @@ public class AIOBServiceImpl implements IAIOBService {
|
|||||||
* @Author haown
|
* @Author haown
|
||||||
* @Date 2024-9-24 15:08
|
* @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 scriptInfoTaskInfo = new ScriptInfoTaskInfo();
|
||||||
scriptInfoTaskInfo.setScriptInfoId(signPatientManageRouteNode.getScriptInfoId());
|
scriptInfoTaskInfo.setScriptInfoId(signPatientManageRouteNode.getScriptInfoId());
|
||||||
scriptInfoTaskInfo.setRobotId(signPatientManageRouteNode.getRobotPublishId());
|
scriptInfoTaskInfo.setRobotId(signPatientManageRouteNode.getRobotPublishId());
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user