百度外呼录音获取。
This commit is contained in:
parent
87175fac69
commit
403603ab7b
@ -30,6 +30,8 @@ xinelu:
|
||||
rich-text-picture-url: /richTextPictureUrl
|
||||
# 资讯富文本的上传路径
|
||||
info-rich-text-picture-url: /infoRichTextPictureUrl
|
||||
# 资讯富文本的上传路径
|
||||
phone-dial-record-video: /phoneDialRecordVideo
|
||||
|
||||
# 开发环境配置
|
||||
server:
|
||||
|
||||
@ -86,6 +86,11 @@ public class SystemBusinessConfig {
|
||||
*/
|
||||
private String richTextPictureUrl;
|
||||
|
||||
/**
|
||||
* AI电话录音地址
|
||||
*/
|
||||
private String phoneDialRecordVideo;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@ -232,4 +237,12 @@ public class SystemBusinessConfig {
|
||||
public void setInfoRichTextPictureUrl(String infoRichTextPictureUrl) {
|
||||
this.infoRichTextPictureUrl = infoRichTextPictureUrl;
|
||||
}
|
||||
|
||||
public String getPhoneDialRecordVideo() {
|
||||
return phoneDialRecordVideo;
|
||||
}
|
||||
|
||||
public void setPhoneDialRecordVideo(String phoneDialRecordVideo) {
|
||||
this.phoneDialRecordVideo = phoneDialRecordVideo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ public class AgencyController extends BaseController {
|
||||
*/
|
||||
@GetMapping("/selectAgencyList")
|
||||
public AjaxResult selectAgencyByIdList(Agency agency) {
|
||||
return agencyService.selectAgencyByIdList(agency);
|
||||
return AjaxResult.success(agencyService.selectAgencyByIdList(agency));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,7 +60,7 @@ public class AgencyController extends BaseController {
|
||||
if (Objects.isNull(agency) || Objects.isNull(agency.getParentId())) {
|
||||
return AjaxResult.success();
|
||||
}
|
||||
return agencyService.selectAgencyByIdList(agency);
|
||||
return AjaxResult.success(agencyService.selectAgencyByIdList(agency));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -96,4 +96,10 @@ public class AIOBController extends BaseController {
|
||||
public JSONObject taskCallBack(@RequestBody TaskCallbackDto taskCallbackDto) throws ClientException {
|
||||
return aiobService.taskCallBack(taskCallbackDto.getCallbackType(), taskCallbackDto.getData());
|
||||
}
|
||||
|
||||
@ApiOperation("任务单通电话回调")
|
||||
@GetMapping("/record")
|
||||
public String record() throws ClientException {
|
||||
return aiobService.record("1726726696448834_936326");
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import com.xinelu.common.utils.poi.ExcelUtil;
|
||||
import com.xinelu.manage.domain.signpatientmanageroute.SignPatientManageRoute;
|
||||
import com.xinelu.manage.dto.manualfollowup.ManualFollowUpDTO;
|
||||
import com.xinelu.manage.dto.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
|
||||
import com.xinelu.manage.dto.signpatientmanageroutenode.CreateAiboActualTimeTaskDto;
|
||||
import com.xinelu.manage.service.signpatientmanageroute.ISignPatientManageRouteService;
|
||||
import com.xinelu.manage.vo.manualfollowup.ManualFollowUpVO;
|
||||
import com.xinelu.manage.vo.signpatientmanageroute.SignPatientManageRouteVO;
|
||||
@ -114,6 +115,20 @@ public class SignPatientManageRouteController extends BaseController {
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 随访待办列表-创建实时呼叫任务
|
||||
* @Param createAiboActualTimeTaskDto 创建百度外呼实时任务传输对象
|
||||
* @return 结果
|
||||
* @Author haown
|
||||
* @Date 2024-11-4 16:06
|
||||
*/
|
||||
@ApiOperation("随访待办列表-创建实时呼叫任务")
|
||||
@PostMapping("/createActualTimeTask")
|
||||
public R<String> createActualTimeTask(@RequestBody CreateAiboActualTimeTaskDto createAiboActualTimeTaskDto) {
|
||||
Long memberId = signPatientManageRouteService.createActualTimeTask(createAiboActualTimeTaskDto);
|
||||
return memberId != null && memberId > 0L ? R.ok() : R.fail();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询人工随访患者基本信息
|
||||
*/
|
||||
|
||||
@ -130,6 +130,15 @@ public class SignPatientManageRouteNodeController extends BaseController {
|
||||
return R.ok(signNodeService.getSpecialDiseaseNode(patientTaskDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* AI通话获取录音
|
||||
*/
|
||||
@ApiOperation("AI通话获取录音")
|
||||
@GetMapping("/getPhoneDialVideo/{id}")
|
||||
public R<String> getPhoneDialVideo(@PathVariable("id") Long id) {
|
||||
return R.ok(signNodeService.getPhoneDialVideo(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试生成患者档案列表数据用
|
||||
*/
|
||||
|
||||
@ -104,6 +104,17 @@ public class PhoneDialRecord extends BaseEntity {
|
||||
@Excel(name = "推送结果状态码,success:成功,fail:失败")
|
||||
private String errorStatus;
|
||||
|
||||
/**
|
||||
* 生成通话录音唯一标识,可通过该标识,获取录音
|
||||
*/
|
||||
@ApiModelProperty(value = "生成通话录音唯一标识,可通过该标识,获取录音")
|
||||
private String ctUuid;
|
||||
|
||||
/**
|
||||
* 通话录音存储路径
|
||||
*/
|
||||
@ApiModelProperty(value = "通话录音存储路径")
|
||||
private String phoneDialRecordVideo;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@ -409,4 +409,5 @@ public class SignPatientManageRouteNode extends BaseEntity {
|
||||
|
||||
@ApiModelProperty(value = "第三方返回的任务ID")
|
||||
private String taskIdExt;
|
||||
|
||||
}
|
||||
|
||||
@ -3,14 +3,13 @@ package com.xinelu.manage.dto.manualfollowup;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.xinelu.common.core.domain.BaseEntity;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import java.time.LocalDate;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 人工随访查询DTO
|
||||
*
|
||||
@ -79,4 +78,10 @@ public class ManualFollowUpDTO extends BaseEntity {
|
||||
private String timeSign;
|
||||
|
||||
private String phoneNodeExecuteResultStatus;
|
||||
|
||||
/**
|
||||
* AI:自动 或 COMMON:手动
|
||||
*/
|
||||
@ApiModelProperty(value = "AI:自动 或 COMMON:手动")
|
||||
private String phoneDialMethod;
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
package com.xinelu.manage.dto.signpatientmanageroutenode;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description: 创建百度外呼实时任务传输对象
|
||||
* @author: haown
|
||||
* @create: 2024-11-04 15:54
|
||||
**/
|
||||
@ApiModel("创建百度外呼实时任务传输对象")
|
||||
@Data
|
||||
public class CreateAiboActualTimeTaskDto {
|
||||
|
||||
@ApiModelProperty("任务表ID")
|
||||
private Long signPatientManageRouteNodeId;
|
||||
|
||||
@ApiModelProperty("话术表主键")
|
||||
private Long scriptInfoId;
|
||||
|
||||
@ApiModelProperty("签约路径表主键")
|
||||
private Long manageRouteId;
|
||||
}
|
||||
@ -59,4 +59,10 @@ public class FollowUpRateDto {
|
||||
@ApiModelProperty(value = "就诊方式,门诊:OUTPATIENT_SERVICE,住院:BE_IN_HOSPITAL")
|
||||
private String visitMethod;
|
||||
|
||||
/**
|
||||
* 统计类型,科室:dept, 日期:date
|
||||
*/
|
||||
@ApiModelProperty(value = "统计类型,科室:dept, 日期:date")
|
||||
private String type;
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ package com.xinelu.manage.mapper.patientvisitrecord;
|
||||
|
||||
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
|
||||
import com.xinelu.manage.dto.patientvisitrecord.PatientVisitRecordDto;
|
||||
import com.xinelu.manage.dto.statistics.FollowUpRateDto;
|
||||
import com.xinelu.manage.vo.patientvisitrecord.PatientVisitRecordStatisticVo;
|
||||
import com.xinelu.manage.vo.patientvisitrecord.PatientVisitRecordVo;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@ -76,4 +78,6 @@ public interface PatientVisitRecordMapper {
|
||||
*/
|
||||
PatientVisitRecord getLastRecord(PatientVisitRecordDto patientVisitRecordDto);
|
||||
|
||||
List<PatientVisitRecordStatisticVo> getVisitPatientList(FollowUpRateDto queryDto);
|
||||
|
||||
}
|
||||
|
||||
@ -61,4 +61,6 @@ public interface PhoneDialRecordMapper {
|
||||
int deletePhoneDialRecordByIds(Long[] ids);
|
||||
|
||||
List<PhoneDialRecordVo> getPhoneDialStatistic(FollowUpRateDto queryDto);
|
||||
|
||||
PhoneDialRecord getLastRecord(Long manageRouteNodeId);
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.xinelu.manage.mapper.signpatientmanageroutenode;
|
||||
import com.xinelu.manage.domain.signpatientmanageroutenode.SignPatientManageRouteNode;
|
||||
import com.xinelu.manage.dto.signpatientmanageroutenode.PatientTaskDto;
|
||||
import com.xinelu.manage.dto.signpatientmanageroutenode.SignPatientManageRouteNodeDto;
|
||||
import com.xinelu.manage.dto.statistics.FollowUpRateDto;
|
||||
import com.xinelu.manage.vo.homepage.PatientAndNode;
|
||||
import com.xinelu.manage.vo.signpatientmanageroutenode.*;
|
||||
import com.xinelu.manage.vo.specialdiseasenode.SpecialDiseaseNodeAuditVo;
|
||||
@ -178,4 +179,6 @@ public interface SignPatientManageRouteNodeMapper {
|
||||
* @return PatientAndNode
|
||||
*/
|
||||
List<PatientAndNode> selectNodeExecuteStatus();
|
||||
|
||||
List<PatientFollowUpPlanVo> getFollowUpPlan(FollowUpRateDto queryDto);
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public interface IAgencyService {
|
||||
* @param agency 机构信息
|
||||
* @return 机构信息集合
|
||||
*/
|
||||
AjaxResult selectAgencyByIdList(Agency agency);
|
||||
List<Agency> selectAgencyByIdList(Agency agency);
|
||||
|
||||
/**
|
||||
* 新增机构信息
|
||||
|
||||
@ -101,7 +101,7 @@ public class AgencyServiceImpl implements IAgencyService {
|
||||
* @return 机构信息
|
||||
*/
|
||||
@Override
|
||||
public AjaxResult selectAgencyByIdList(Agency agency) {
|
||||
public List<Agency> selectAgencyByIdList(Agency agency) {
|
||||
// 查询用户角色
|
||||
List<SysRole> roleList = SecurityUtils.getLoginUser().getUser().getRoles();
|
||||
if (CollectionUtils.isNotEmpty(roleList)) {
|
||||
@ -110,7 +110,7 @@ public class AgencyServiceImpl implements IAgencyService {
|
||||
agency.setId(SecurityUtils.getLoginUser().getUser().getHospitalAgencyId());
|
||||
}
|
||||
}
|
||||
return AjaxResult.success(agencyMapper.selectAgencyList(agency));
|
||||
return agencyMapper.selectAgencyList(agency);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -71,4 +71,6 @@ public interface IAIOBService {
|
||||
* @Date 2024-9-2 14:20
|
||||
*/
|
||||
JSONObject taskCallBack(Integer callbackType, TaskCallbackDataDto data) throws ClientException;
|
||||
|
||||
String record(String ccUUID);
|
||||
}
|
||||
|
||||
@ -6,7 +6,9 @@ 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.config.SystemBusinessConfig;
|
||||
import com.xinelu.common.constant.AiboTaskTypeContant;
|
||||
import com.xinelu.common.constant.Constants;
|
||||
import com.xinelu.common.constant.PhoneMessageRemindConstants;
|
||||
import com.xinelu.common.constant.TaskCreateTypeConstant;
|
||||
import com.xinelu.common.constant.TaskStatisticsTypeConstants;
|
||||
@ -66,11 +68,19 @@ import com.xinelu.manage.service.signpatientmanageroutenode.ISignPatientManageRo
|
||||
import com.xinelu.manage.vo.aibo.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;
|
||||
@ -112,6 +122,9 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
@Resource
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Resource
|
||||
private SystemBusinessConfig systemBusinessConfig;
|
||||
|
||||
@Resource
|
||||
private SignPatientRecordMapper signPatientRecordMapper;
|
||||
@Resource
|
||||
@ -364,6 +377,10 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
if (ObjectUtils.isNotEmpty(signPatientManageRouteNode)) {
|
||||
// 标记任务执行状态
|
||||
signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.EXECUTED.getInfo());
|
||||
// 问卷设置任务完成时间
|
||||
if (StringUtils.equals(TaskNodeTypeEnum.QUESTIONNAIRE_SCALE.getInfo(), signPatientManageRouteNode.getTaskNodeType())) {
|
||||
signPatientManageRouteNode.setNodeFinishDate(LocalDateTime.now());
|
||||
}
|
||||
//接通状态,1-已接通 0-未接通
|
||||
if (data.getEndType() != null && data.getEndType() == 0) {
|
||||
// 设置电话拨通情况
|
||||
@ -444,6 +461,10 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
phoneDialRecord.setErrorCode(data.getEndType() == 0 ? 1L : 0);
|
||||
phoneDialRecord.setErrorStatus(data.getEndType() == 0 ? ErrorStatusEnum.fail.getValue() : ErrorStatusEnum.success.getValue());
|
||||
phoneDialRecord.setCreateTime(LocalDateTime.now());
|
||||
|
||||
phoneDialRecord.setCtUuid(data.getContactUUID());
|
||||
phoneDialRecord.setPhoneDialRecordVideo(getPhoneDialRecord(data.getContactUUID()));
|
||||
|
||||
phoneDialRecordMapper.insertPhoneDialRecord(phoneDialRecord);
|
||||
|
||||
// 修改任务统计表数据
|
||||
@ -462,6 +483,38 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
return retObj;
|
||||
}
|
||||
|
||||
@Override public String record(String ccUUID) {
|
||||
String accessToken = getAccessToken();
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("Authorization", accessToken);
|
||||
|
||||
HttpEntity<JSONObject> requestEntity = new HttpEntity<>(null, headers);
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("contactUuid", ccUUID);
|
||||
params.put("expiration", 1800);
|
||||
params.put("operation", 3);
|
||||
ResponseEntity<String> responseEntity = restTemplate.exchange(url + "/v1/record"+"?contactUuid={contactUuid}&expiration={expiration}&operation={operation}", HttpMethod.GET, requestEntity, String.class, params);
|
||||
//{
|
||||
// "requestId" : "9c5870a37e2441ad9ccc9100d870054e",
|
||||
// "time" : 1730701318185,
|
||||
// "code" : 200,
|
||||
// "msg" : "OK",
|
||||
// "data" : [ {
|
||||
// "recordUrl" : "https://gz.bcebos.com/v1/cc-call-recording/2024/09/19/3849515568332800/14/1726726696417508_628800_1726726696448834_936326_14_18_42.wav?authorization=bce-auth-v1%2FALTAKOVf6H3DUWVqVqc2k43RAa%2F2024-11-04T06%3A21%3A58Z%2F1800%2F%2Fe33651c189f512aaa3c94f68f8136dc69538c680c94c8605696de5a041c36f49",
|
||||
// "downloadUrl" : "https://gz.bcebos.com/v1/cc-call-recording/2024/09/19/3849515568332800/14/1726726696417508_628800_1726726696448834_936326_14_18_42.wav?responseContentDisposition=attachment%3B%20filename%3D1726726696417508_628800_1726726696448834_936326_14_18_42.wav&authorization=bce-auth-v1%2FALTAKOVf6H3DUWVqVqc2k43RAa%2F2024-11-04T06%3A21%3A58Z%2F1800%2F%2Fa802d88ba4b987f1a0f30ce73b515c8515255b34e5bac4f1d0c27987ac70d68a"
|
||||
// } ]
|
||||
//}
|
||||
JSONObject object = JSON.parseObject(responseEntity.getBody());
|
||||
if (object == null || object.getInteger("code") == null || object.getInteger("code") != 200) {
|
||||
return null;
|
||||
}
|
||||
JSONArray data = object.getJSONArray("data");
|
||||
JSONObject obj = data.getJSONObject(0);
|
||||
return obj.getOrDefault("downloadUrl", null).toString();
|
||||
}
|
||||
|
||||
private void sendSms(Long patientId, SignPatientManageRouteNode signPatientManageRouteNode) throws ClientException {
|
||||
TextMessage textMessage = textMessageMapper.selectTextMessageById(signPatientManageRouteNode.getPhoneMessageTemplateId());
|
||||
if (ObjectUtils.isNotEmpty(textMessage)) {
|
||||
@ -551,7 +604,7 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
patientQuestionSubmitResult.setManageRouteId(node.getManageRouteId());
|
||||
patientQuestionSubmitResult.setManageRouteName(node.getManageRouteName());
|
||||
patientQuestionSubmitResult.setManageRouteNodeId(node.getId());
|
||||
patientQuestionSubmitResult.setManageRouteNodeName(node.getManageRouteName());
|
||||
patientQuestionSubmitResult.setManageRouteNodeName(node.getRouteNodeName());
|
||||
patientQuestionSubmitResult.setQuestionInfoId(questionInfo.getId());
|
||||
patientQuestionSubmitResult.setDepartmentId(questionInfo.getDepartmentId());
|
||||
patientQuestionSubmitResult.setDepartmentName(questionInfo.getDepartmentName());
|
||||
@ -614,6 +667,32 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
});
|
||||
patientQuestionOptionResultMapper.saveQuestionOptionList(patientQuestionOptionResults);
|
||||
totalScore[0] = totalScore[0].add(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);
|
||||
});
|
||||
patientQuestionOptionResultMapper.saveQuestionOptionList(patientQuestionOptionResults);
|
||||
totalScore[0] = totalScore[0].add(BigDecimal.ZERO);
|
||||
}
|
||||
});
|
||||
|
||||
@ -664,4 +743,43 @@ public class AIOBServiceImpl implements IAIOBService {
|
||||
scriptInfoTaskInfo.setExecuteTime(executeTime.plusMinutes(signPatientManageRouteNode.getPhoneTimeInterval()));
|
||||
scriptInfoTaskInfoMapper.insertScriptInfoTaskInfo(scriptInfoTaskInfo);
|
||||
}
|
||||
|
||||
private String getPhoneDialRecord(String ccUuid) {
|
||||
String url = "";
|
||||
String downLoadUrl = record(ccUuid);
|
||||
if (StringUtils.isNotBlank(downLoadUrl)) {
|
||||
url = systemBusinessConfig.getProfile() + systemBusinessConfig.getPhoneDialRecordVideo() + "/" + ccUuid + ".wav";
|
||||
File outputPath = new File(url);
|
||||
File dir = outputPath.getParentFile();
|
||||
if (!dir.exists()){
|
||||
dir.mkdirs();
|
||||
}
|
||||
try {
|
||||
outputPath.createNewFile(); // 创建文件
|
||||
URL fileUrl = new URL(downLoadUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection)fileUrl.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.connect();
|
||||
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
InputStream inputStream = new BufferedInputStream(connection.getInputStream());
|
||||
FileOutputStream outputStream = new FileOutputStream(outputPath);
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
System.out.println("下载完成,目录:" + outputPath);
|
||||
return Constants.RESOURCE_PREFIX + "/" + systemBusinessConfig.getPhoneDialRecordVideo() + "/" + ccUuid + ".wav";
|
||||
} else {
|
||||
System.out.println("下载失败" + connection.getResponseCode());
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import com.xinelu.common.exception.ServiceException;
|
||||
import com.xinelu.manage.domain.signpatientmanageroute.SignPatientManageRoute;
|
||||
import com.xinelu.manage.dto.manualfollowup.ManualFollowUpDTO;
|
||||
import com.xinelu.manage.dto.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
|
||||
import com.xinelu.manage.dto.signpatientmanageroutenode.CreateAiboActualTimeTaskDto;
|
||||
import com.xinelu.manage.dto.smssend.SmsInfoDTO;
|
||||
import com.xinelu.manage.vo.manualfollowup.ManualFollowUpVO;
|
||||
import com.xinelu.manage.vo.signpatientmanageroute.SignPatientManageRouteVO;
|
||||
@ -14,6 +15,7 @@ import com.xinelu.manage.vo.signpatientrecord.SignPatientRecordSelectVo;
|
||||
import com.xinelu.manage.vo.specialdiseaseroute.SpecialDiseaseRouteAuditVo;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
/**
|
||||
* 签约患者管理任务路径Service接口
|
||||
@ -77,6 +79,15 @@ public interface ISignPatientManageRouteService {
|
||||
*/
|
||||
List<ManualFollowUpVO> selectManualFollowUpList(ManualFollowUpDTO manualFollowUpDTO);
|
||||
|
||||
/**
|
||||
* @description 随访待办列表-创建实时呼叫任务
|
||||
* @Param createAiboActualTimeTaskDto 创建百度外呼实时任务传输对象
|
||||
* @return 结果
|
||||
* @Author haown
|
||||
* @Date 2024-11-4 16:06
|
||||
*/
|
||||
Long createActualTimeTask(@RequestBody CreateAiboActualTimeTaskDto createAiboActualTimeTaskDto);
|
||||
|
||||
/**
|
||||
* 查询人工随访患者基本信息
|
||||
* @param id 签约患者管理任务表id
|
||||
|
||||
@ -33,6 +33,7 @@ import com.xinelu.common.exception.ServiceException;
|
||||
import com.xinelu.common.utils.AgeUtil;
|
||||
import com.xinelu.common.utils.SecurityUtils;
|
||||
import com.xinelu.common.utils.bean.BeanUtils;
|
||||
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;
|
||||
@ -45,12 +46,15 @@ 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.signroutetriggercondition.SignRouteTriggerCondition;
|
||||
import com.xinelu.manage.dto.aibo.ActualTimeTaskDto;
|
||||
import com.xinelu.manage.dto.manualfollowup.ManualFollowUpDTO;
|
||||
import com.xinelu.manage.dto.patientquestionoptionresult.PatientQuestionOptionResultDTO;
|
||||
import com.xinelu.manage.dto.patientquestionsubjectresult.PatientQuestionSubjectResultDTO;
|
||||
import com.xinelu.manage.dto.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
|
||||
import com.xinelu.manage.dto.signpatientmanageroutenode.CreateAiboActualTimeTaskDto;
|
||||
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.patientquestionoptionresult.PatientQuestionOptionResultMapper;
|
||||
import com.xinelu.manage.mapper.patientquestionsubjectresult.PatientQuestionSubjectResultMapper;
|
||||
import com.xinelu.manage.mapper.patientquestionsubmitresult.PatientQuestionSubmitResultMapper;
|
||||
@ -63,6 +67,7 @@ import com.xinelu.manage.mapper.signpatientmanageroute.SignPatientManageRouteMap
|
||||
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
|
||||
import com.xinelu.manage.mapper.signpatientrecord.SignPatientRecordMapper;
|
||||
import com.xinelu.manage.mapper.signroutetriggercondition.SignRouteTriggerConditionMapper;
|
||||
import com.xinelu.manage.service.aibo.IAIOBService;
|
||||
import com.xinelu.manage.service.patienttaskstatistics.IPatientTaskStatisticsService;
|
||||
import com.xinelu.manage.service.propagandainfo.IPropagandaInfoService;
|
||||
import com.xinelu.manage.service.questioninfo.IQuestionInfoService;
|
||||
@ -89,6 +94,7 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -99,6 +105,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -155,6 +162,13 @@ public class SignPatientManageRouteServiceImpl implements ISignPatientManageRout
|
||||
@Resource
|
||||
private IPatientTaskStatisticsService patientTaskStatisticsService;
|
||||
|
||||
@Resource
|
||||
private PatientInfoMapper patientInfoMapper;
|
||||
@Resource
|
||||
private IAIOBService aiobService;
|
||||
@Value("${aiob.callBackUrl}")
|
||||
private String callBackUrl;
|
||||
|
||||
private static final String SUCCESS = "OK";
|
||||
|
||||
/**
|
||||
@ -325,34 +339,6 @@ public class SignPatientManageRouteServiceImpl implements ISignPatientManageRout
|
||||
ArrayList<ManualFollowUpVO> manualFollowUps = new ArrayList<>();
|
||||
for (ManualFollowUpVO manualFollowUpVO : manualFollowUpVOS) {
|
||||
//判断路径节点,组装数据
|
||||
// if (manualFollowUpVO.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_DISCHARGE.getInfo()) || manualFollowUpVO.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_VISIT_DISCHARGE.getInfo())) {
|
||||
// if (manualFollowUpVO.getPatientType().equals(PatientTypeEnum.DISCHARGED_PATIENT.getInfo())) {
|
||||
// LocalDate localDate = manualFollowUpVO.getDischargeTime().plusDays(manualFollowUpVO.getRouteNodeDay()).toLocalDate();
|
||||
// boolean before = localDate.isBefore(LocalDate.now()) || localDate.isEqual(LocalDate.now());
|
||||
// if (before) {
|
||||
// manualFollowUps.add(manualFollowUpVO);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (manualFollowUpVO.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_ADMISSION.getInfo())) {
|
||||
// if (manualFollowUpVO.getPatientType().equals(PatientTypeEnum.IN_HOSPITAL_PATIENT.getInfo())) {
|
||||
// LocalDate localDate = manualFollowUpVO.getAdmissionTime().plusDays(manualFollowUpVO.getRouteNodeDay()).toLocalDate();
|
||||
// boolean before = localDate.isBefore(LocalDate.now()) || localDate.isEqual(LocalDate.now());
|
||||
// if (before) {
|
||||
// manualFollowUps.add(manualFollowUpVO);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (manualFollowUpVO.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_CONSULTATION.getInfo()) || manualFollowUpVO.getRouteNodeName().equals(RouteNodeNameEnum.AFTER_VISIT_DISCHARGE.getInfo())) {
|
||||
// if (manualFollowUpVO.getPatientType().equals(PatientTypeEnum.OUTPATIENT.getInfo()) && manualFollowUpVO.getAdmissionTime() == null) {
|
||||
// LocalDate localDate = manualFollowUpVO.getVisitTime().plusDays(manualFollowUpVO.getRouteNodeDay()).toLocalDate();
|
||||
// boolean before = localDate.isBefore(LocalDate.now()) || localDate.isEqual(LocalDate.now());
|
||||
// if (before) {
|
||||
// manualFollowUps.add(manualFollowUpVO);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//判断路径节点,组装数据
|
||||
LocalDate localDate = null;
|
||||
if (Objects.nonNull(manualFollowUpVO.getDischargeTime())) {
|
||||
localDate = manualFollowUpVO.getDischargeTime().plusDays(manualFollowUpVO.getRouteNodeDay()).toLocalDate();
|
||||
@ -379,7 +365,44 @@ public class SignPatientManageRouteServiceImpl implements ISignPatientManageRout
|
||||
return manualFollowUps;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @description 随访待办列表-创建实时呼叫任务
|
||||
* @Param createAiboActualTimeTaskDto 创建百度外呼实时任务传输对象
|
||||
* @return 结果
|
||||
* @Author haown
|
||||
* @Date 2024-11-4 16:06
|
||||
*/
|
||||
@Override public Long createActualTimeTask(CreateAiboActualTimeTaskDto createAiboActualTimeTaskDto) {
|
||||
ScriptInfo scriptInfo = scriptInfoMapper.selectScriptInfoById(createAiboActualTimeTaskDto.getScriptInfoId());
|
||||
SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(createAiboActualTimeTaskDto.getManageRouteId());
|
||||
PatientInfo patientInfo = patientInfoMapper.selectPatientInfoById(signPatientManageRoute.getPatientId());
|
||||
// 没有任务则创建任务
|
||||
if (ObjectUtils.isNotEmpty(scriptInfo)) {
|
||||
ActualTimeTaskDto actualTimeTaskDto = new ActualTimeTaskDto();
|
||||
actualTimeTaskDto.setRobotId(scriptInfo.getRobotPublishId());
|
||||
actualTimeTaskDto.setMobile(patientInfo.getPatientPhone());
|
||||
actualTimeTaskDto.setSecretType(2);
|
||||
actualTimeTaskDto.setStopDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 17:00:00");
|
||||
// 查询患者画像信息
|
||||
List<LabelFieldInfoContentVo> labelFieldContentList = labelFieldContentMapper.selectByPatientId(patientInfo.getId());
|
||||
// 处理变量
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
if (com.xinelu.common.utils.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());
|
||||
});
|
||||
}
|
||||
actualTimeTaskDto.setDialogVar(jsonObject);
|
||||
actualTimeTaskDto.setCallBackUrl(callBackUrl);
|
||||
actualTimeTaskDto.setExtJson(createAiboActualTimeTaskDto.getSignPatientManageRouteNodeId()+ "");
|
||||
return aiobService.createActualTimeTask(actualTimeTaskDto);
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询人工随访患者基本信息
|
||||
*
|
||||
* @param id 签约患者管理任务表id
|
||||
|
||||
@ -20,7 +20,6 @@ import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 签约患者管理任务路径节点Service接口
|
||||
*
|
||||
@ -131,6 +130,8 @@ public interface ISignPatientManageRouteNodeService {
|
||||
|
||||
List<PatientSpecialDiseaseNodeVo> getSpecialDiseaseNode(PatientTaskDto patientTaskDto);
|
||||
|
||||
String getPhoneDialVideo(Long id);
|
||||
|
||||
/**
|
||||
* 根据参数列表修改任务
|
||||
* @param paramsCurrentLists 参数列表
|
||||
|
||||
@ -27,6 +27,7 @@ import com.xinelu.manage.domain.patientnodeparamscurrent.PatientNodeParamsCurren
|
||||
import com.xinelu.manage.domain.patienttaskexecuterecord.PatientTaskExecuteRecord;
|
||||
import com.xinelu.manage.domain.patienttaskstatistics.PatientTaskStatistics;
|
||||
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
|
||||
import com.xinelu.manage.domain.phonedialrecord.PhoneDialRecord;
|
||||
import com.xinelu.manage.domain.propagandainfo.PropagandaInfo;
|
||||
import com.xinelu.manage.domain.questioninfo.QuestionInfo;
|
||||
import com.xinelu.manage.domain.scriptInfo.ScriptInfo;
|
||||
@ -50,6 +51,7 @@ import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper;
|
||||
import com.xinelu.manage.mapper.patientquestionsubmitresult.PatientQuestionSubmitResultMapper;
|
||||
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.scriptInfo.ScriptInfoMapper;
|
||||
import com.xinelu.manage.mapper.signpatientmanageroute.SignPatientManageRouteMapper;
|
||||
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
|
||||
@ -154,6 +156,8 @@ public class SignPatientManageRouteNodeServiceImpl implements ISignPatientManage
|
||||
private PatientTaskExecuteRecordMapper patientTaskExecuteRecordMapper;
|
||||
@Resource
|
||||
private IPatientTaskStatisticsService patientTaskStatisticsService;
|
||||
@Resource
|
||||
private PhoneDialRecordMapper phoneDialRecordMapper;
|
||||
|
||||
/**
|
||||
* 查询签约患者管理任务路径节点
|
||||
@ -579,6 +583,11 @@ public class SignPatientManageRouteNodeServiceImpl implements ISignPatientManage
|
||||
return specialDiseaseNodeMapper.selectRouteNodeByRouteId(manageRouteList.get(0).getRouteId());
|
||||
}
|
||||
|
||||
@Override public String getPhoneDialVideo(Long id) {
|
||||
PhoneDialRecord phoneDialRecord = phoneDialRecordMapper.getLastRecord(id);
|
||||
return ObjectUtils.isEmpty(phoneDialRecord) ? null : phoneDialRecord.getPhoneDialRecordVideo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成有参数得任务
|
||||
* @param routeNodeId 节点id
|
||||
|
||||
@ -1,23 +1,36 @@
|
||||
package com.xinelu.manage.service.statistics.impl;
|
||||
|
||||
import com.xinelu.common.core.domain.entity.SysUser;
|
||||
import com.xinelu.common.enums.NodeTypeEnum;
|
||||
import com.xinelu.common.enums.PhoneDialMethodEnum;
|
||||
import com.xinelu.common.utils.StringUtils;
|
||||
import com.xinelu.manage.domain.agency.Agency;
|
||||
import com.xinelu.manage.domain.department.Department;
|
||||
import com.xinelu.manage.dto.statistics.FollowUpRateDto;
|
||||
import com.xinelu.manage.mapper.patientvisitrecord.PatientVisitRecordMapper;
|
||||
import com.xinelu.manage.mapper.phonedialrecord.PhoneDialRecordMapper;
|
||||
import com.xinelu.manage.mapper.shortmessagesendrecord.ShortMessageSendRecordMapper;
|
||||
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
|
||||
import com.xinelu.manage.mapper.subscribemessagesendrecord.SubscribeMessageSendRecordMapper;
|
||||
import com.xinelu.manage.service.agency.IAgencyService;
|
||||
import com.xinelu.manage.service.department.IDepartmentService;
|
||||
import com.xinelu.manage.service.statistics.IStatisticsService;
|
||||
import com.xinelu.manage.vo.patientvisitrecord.PatientVisitRecordStatisticVo;
|
||||
import com.xinelu.manage.vo.phonedialrecord.PhoneDialRecordVo;
|
||||
import com.xinelu.manage.vo.signpatientmanageroutenode.PatientFollowUpPlanVo;
|
||||
import com.xinelu.manage.vo.statistics.FollowUpDetailVo;
|
||||
import com.xinelu.manage.vo.statistics.FollowUpNumTrendVo;
|
||||
import com.xinelu.manage.vo.statistics.FollowUpRateTrendVo;
|
||||
import com.xinelu.manage.vo.statistics.FollowUpRateVo;
|
||||
import com.xinelu.manage.vo.statistics.MessageSendVo;
|
||||
import com.xinelu.system.service.ISysUserService;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -40,6 +53,16 @@ public class StatisticsServiceImpl implements IStatisticsService {
|
||||
private ShortMessageSendRecordMapper shortMessageSendRecordMapper;
|
||||
@Resource
|
||||
private SubscribeMessageSendRecordMapper subscribeMessageSendRecordMapper;
|
||||
@Resource
|
||||
private PatientVisitRecordMapper patientVisitRecordMapper;
|
||||
@Resource
|
||||
private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
|
||||
@Resource
|
||||
private IAgencyService agencyService;
|
||||
@Resource
|
||||
private IDepartmentService departmentService;
|
||||
@Resource
|
||||
private ISysUserService userService;
|
||||
|
||||
/**
|
||||
* @description 随访成功率统计
|
||||
@ -130,7 +153,101 @@ public class StatisticsServiceImpl implements IStatisticsService {
|
||||
*/
|
||||
@Override
|
||||
public List<FollowUpDetailVo> getFollowUpDetail(FollowUpRateDto queryDto) {
|
||||
return null;
|
||||
List<FollowUpDetailVo> retList = new ArrayList<>();
|
||||
FollowUpDetailVo followUpDetailVo = new FollowUpDetailVo();
|
||||
// 总计行预留位置
|
||||
retList.set(0, followUpDetailVo);
|
||||
// 就诊患者列表查询
|
||||
List<PatientVisitRecordStatisticVo> patientVisitList = patientVisitRecordMapper.getVisitPatientList(queryDto);
|
||||
// 随访计划列表查询
|
||||
List<PatientFollowUpPlanVo> planList = signPatientManageRouteNodeMapper.getFollowUpPlan(queryDto);
|
||||
|
||||
if (StringUtils.equals(queryDto.getType(), "dept")) {
|
||||
// 就诊患者列表按照科室分组
|
||||
Map<Long, List<PatientVisitRecordStatisticVo>> groupByDept = new HashMap<>();
|
||||
if (CollectionUtils.isNotEmpty(patientVisitList)) {
|
||||
groupByDept = patientVisitList.stream().collect(Collectors.groupingBy(PatientVisitRecordStatisticVo::getDepartmentId));
|
||||
}
|
||||
|
||||
Map<Long, List<PatientFollowUpPlanVo>> planGroupByDept = new HashMap<>();
|
||||
if (CollectionUtils.isNotEmpty(planList)) {
|
||||
// 随访计划列表按照科室分组
|
||||
planGroupByDept = planList.stream().collect(Collectors.groupingBy(PatientFollowUpPlanVo::getDepartmentId));
|
||||
}
|
||||
// 查询机构、科室、医生列表
|
||||
Agency agencyQuery = new Agency();
|
||||
agencyQuery.setId(queryDto.getHospitalAgencyId());
|
||||
List<Agency> agencyList = agencyService.selectAgencyByIdList(agencyQuery);
|
||||
for (Agency agency : agencyList) {
|
||||
// 根据机构列表查询科室
|
||||
Department deptQuery = new Department();
|
||||
deptQuery.setHospitalAgencyId(agency.getId());
|
||||
deptQuery.setNodeType(NodeTypeEnum.DEPARTMENT.getInfo());
|
||||
List<Department> deptList = departmentService.selectDepartmentList(deptQuery);
|
||||
for (Department dept : deptList) {
|
||||
followUpDetailVo.setRowName(dept.getDepartmentName());
|
||||
// 就诊人数
|
||||
List<PatientVisitRecordStatisticVo> deptVisitList = groupByDept.get(dept.getId());
|
||||
followUpDetailVo.setPatientNum(CollectionUtils.isEmpty(deptVisitList) ? 0 : groupByDept.get(dept.getId()).size());
|
||||
|
||||
// 科室统计随访计划人数、随访覆盖率、随访成功人数、随访成功率
|
||||
List<PatientFollowUpPlanVo> deptPlanList = planGroupByDept.get(dept.getId());
|
||||
getFollowUpDetailVo(deptPlanList, followUpDetailVo);
|
||||
|
||||
// 查询科室医生
|
||||
SysUser userQuery = new SysUser();
|
||||
userQuery.setHospitalAgencyId(dept.getHospitalAgencyId());
|
||||
userQuery.setDepartmentId(dept.getId());
|
||||
List<SysUser> userList = userService.selectUserList(userQuery);
|
||||
List<FollowUpDetailVo> childrenList = new ArrayList<>();
|
||||
|
||||
Map<Long, List<PatientVisitRecordStatisticVo>> patientGroupByDoctor = deptVisitList.stream().collect(Collectors.groupingBy(PatientVisitRecordStatisticVo::getAttendingPhysicianId));
|
||||
Map<Long, List<PatientFollowUpPlanVo>> planGroupByDoctor = deptPlanList.stream().collect(Collectors.groupingBy(PatientFollowUpPlanVo::getAttendingPhysicianId));
|
||||
|
||||
for (SysUser user : userList) {
|
||||
FollowUpDetailVo childRow = new FollowUpDetailVo();
|
||||
childRow.setRowName(user.getNickName());
|
||||
|
||||
// 医生就诊人数
|
||||
childRow.setPatientNum(CollectionUtils.isEmpty(patientGroupByDoctor.get(user.getUserId())) ? 0 : planGroupByDoctor.get(user.getUserId()).size());
|
||||
|
||||
// 医生统计随访计划人数、随访覆盖率、随访成功人数、随访成功率
|
||||
List<PatientFollowUpPlanVo> doctorPlanList = planGroupByDoctor.get(dept.getId());
|
||||
getFollowUpDetailVo(doctorPlanList, childRow);
|
||||
childrenList.add(childRow);
|
||||
}
|
||||
|
||||
followUpDetailVo.setChilderenList(childrenList);
|
||||
retList.add(followUpDetailVo);
|
||||
}
|
||||
}
|
||||
} else if (StringUtils.equals(queryDto.getType(), "date")){
|
||||
// 日期列表
|
||||
List<String> months = new ArrayList<>();
|
||||
LocalDate startDate = queryDto.getStartDate();
|
||||
while (!startDate.isAfter(queryDto.getEndDate())) {
|
||||
months.add(startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")));
|
||||
startDate = startDate.plus(1, ChronoUnit.MONTHS);
|
||||
}
|
||||
// 就诊患者列表按照就诊日期分组
|
||||
Map<String, List<PatientVisitRecordStatisticVo>> groupByVisitDate = new HashMap<>();
|
||||
if (CollectionUtils.isNotEmpty(patientVisitList)) {
|
||||
groupByVisitDate = patientVisitList.stream().collect(Collectors.groupingBy(PatientVisitRecordStatisticVo::getDischargeTimeMonthStr));
|
||||
}
|
||||
|
||||
Map<String, List<PatientFollowUpPlanVo>> planGroupByExecuteDate = new HashMap<>();
|
||||
if (CollectionUtils.isNotEmpty(planList)) {
|
||||
// 随访计划列表按照计划日期分组
|
||||
planGroupByExecuteDate = planList.stream().collect(Collectors.groupingBy(PatientFollowUpPlanVo::getExecuteMonthStr));
|
||||
}
|
||||
for (String month : months) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 计算总计行
|
||||
getTotalRow(retList);
|
||||
return retList;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,4 +306,59 @@ public class StatisticsServiceImpl implements IStatisticsService {
|
||||
return retObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 统计随访计划人数、随访覆盖率、随访成功人数、随访成功率
|
||||
* @Param planList 随访计划
|
||||
* @Param followUpDetailVo 随访明细表
|
||||
* @Author haown
|
||||
* @Date 2024-11-4 11:13
|
||||
*/
|
||||
private FollowUpDetailVo getFollowUpDetailVo(List<PatientFollowUpPlanVo> planList, FollowUpDetailVo followUpDetailVo) {
|
||||
if (followUpDetailVo.getPatientNum() == 0) {
|
||||
followUpDetailVo.setFollowUpNum(0);
|
||||
followUpDetailVo.setFollowUpCoverRate(BigDecimal.ZERO);
|
||||
followUpDetailVo.setFollowUpSuccessNum(0);
|
||||
followUpDetailVo.setFollowUpSuccessRate(BigDecimal.ZERO);
|
||||
return followUpDetailVo;
|
||||
}
|
||||
// 按照patientId分组
|
||||
Map<Long, List<PatientFollowUpPlanVo>> groupByPatient = planList.stream().collect(Collectors.groupingBy(PatientFollowUpPlanVo::getPatientId));
|
||||
// 有随访计划人数
|
||||
followUpDetailVo.setFollowUpNum(groupByPatient.keySet().size());
|
||||
// 随访覆盖率
|
||||
followUpDetailVo.setFollowUpCoverRate(new BigDecimal(followUpDetailVo.getFollowUpNum()).divide(new BigDecimal(followUpDetailVo.getPatientNum()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
|
||||
|
||||
// 随访成功人数
|
||||
Map<Long, List<PatientFollowUpPlanVo>> groupByFinishStatus = planList.stream().filter(item -> item.getTaskFinishStatus() == 1).collect(Collectors.groupingBy(PatientFollowUpPlanVo::getPatientId));
|
||||
followUpDetailVo.setFollowUpSuccessNum(groupByFinishStatus.keySet().size());
|
||||
// 随访成功率
|
||||
followUpDetailVo.setFollowUpSuccessRate(new BigDecimal(followUpDetailVo.getFollowUpSuccessNum()).divide(new BigDecimal(followUpDetailVo.getPatientNum()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
|
||||
|
||||
return followUpDetailVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 计算总计行就诊人数、随访计划人数、随访覆盖率、随访成功人数、随访成功率
|
||||
* @Param * @param null
|
||||
* @return 列表数据
|
||||
* @Author haown
|
||||
* @Date 2024-11-4 11:29
|
||||
*/
|
||||
private List<FollowUpDetailVo> getTotalRow(List<FollowUpDetailVo> followUpDetailVoList) {
|
||||
for (FollowUpDetailVo retObj : followUpDetailVoList) {
|
||||
retObj.setRowName("总计");
|
||||
// 就诊人数
|
||||
retObj.setPatientNum(followUpDetailVoList.stream().map(FollowUpDetailVo::getPatientNum).reduce(Integer::sum).get());
|
||||
// 随访计划人数
|
||||
retObj.setFollowUpNum(followUpDetailVoList.stream().map(FollowUpDetailVo::getFollowUpNum).reduce(Integer::sum).get());
|
||||
// 随访覆盖率
|
||||
retObj.setFollowUpCoverRate(new BigDecimal(retObj.getFollowUpNum()).divide(new BigDecimal(retObj.getPatientNum()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
|
||||
// 随访成功人数
|
||||
retObj.setFollowUpSuccessNum(followUpDetailVoList.stream().map(FollowUpDetailVo::getFollowUpSuccessNum).reduce(Integer::sum).get());
|
||||
// 随访成功率
|
||||
retObj.setFollowUpCoverRate(new BigDecimal(retObj.getFollowUpSuccessNum()).divide(new BigDecimal(retObj.getPatientNum()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")));
|
||||
followUpDetailVoList.set(0, retObj);
|
||||
}
|
||||
return followUpDetailVoList;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,9 @@ package com.xinelu.manage.vo.manualfollowup;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 人工随访代办VO
|
||||
@ -143,7 +142,19 @@ public class ManualFollowUpVO {
|
||||
@ApiModelProperty(value = "任务节点类型,电话外呼:PHONE_OUTBOUND,问卷量表:QUESTIONNAIRE_SCALE,宣教文章:PROPAGANDA_ARTICLE,文字提醒:TEXT_REMIND")
|
||||
private String taskNodeType;
|
||||
|
||||
/**
|
||||
* AI:自动 或 COMMON:手动
|
||||
*/
|
||||
@ApiModelProperty(value = "AI:自动 或 COMMON:手动")
|
||||
private String phoneDialMethod;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@ApiModelProperty(value = "计划时间")
|
||||
private LocalDate planTime;
|
||||
|
||||
/**
|
||||
* 生成通话录音唯一标识,可通过该标识,获取录音
|
||||
*/
|
||||
@ApiModelProperty(value = "生成通话录音唯一标识,可通过该标识,获取录音")
|
||||
private String ctUUID;
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package com.xinelu.manage.vo.patientvisitrecord;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description: 就诊记录统计返回视图类
|
||||
* @author: haown
|
||||
* @create: 2024-11-01 15:03
|
||||
**/
|
||||
@ApiModel("就诊记录统计返回视图类")
|
||||
@Data
|
||||
public class PatientVisitRecordStatisticVo {
|
||||
|
||||
/**
|
||||
* 所属医院id
|
||||
*/
|
||||
@ApiModelProperty(value = "所属医院id")
|
||||
private Long hospitalAgencyId;
|
||||
|
||||
/**
|
||||
* 所属医院名称
|
||||
*/
|
||||
@ApiModelProperty(value = "所属医院名称")
|
||||
private String hospitalAgencyName;
|
||||
|
||||
/**
|
||||
* 所属院区id
|
||||
*/
|
||||
@ApiModelProperty(value = "所属院区id")
|
||||
private Long campusAgencyId;
|
||||
|
||||
/**
|
||||
* 所属院区名称
|
||||
*/
|
||||
@ApiModelProperty(value = "所属院区名称")
|
||||
private String campusAgencyName;
|
||||
|
||||
/**
|
||||
* 所属科室id
|
||||
*/
|
||||
@ApiModelProperty(value = "所属科室id")
|
||||
private Long departmentId;
|
||||
|
||||
/**
|
||||
* 所属科室名称
|
||||
*/
|
||||
@ApiModelProperty(value = "所属科室名称")
|
||||
private String departmentName;
|
||||
|
||||
/**
|
||||
* 所属病区id
|
||||
*/
|
||||
@ApiModelProperty(value = "所属病区id")
|
||||
private Long wardId;
|
||||
|
||||
/**
|
||||
* 所属病区名称
|
||||
*/
|
||||
@ApiModelProperty(value = "所属病区名称")
|
||||
private String wardName;
|
||||
|
||||
/** 主治医生id */
|
||||
@ApiModelProperty(value = "主治医生id")
|
||||
private Long attendingPhysicianId;
|
||||
|
||||
/** 主治医生姓名 */
|
||||
@ApiModelProperty(value = "主治医生姓名")
|
||||
private String attendingPhysicianName;
|
||||
|
||||
/** 出院时间 */
|
||||
@ApiModelProperty(value = "出院时间月份")
|
||||
private String dischargeTimeMonthStr;
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.xinelu.manage.vo.signpatientmanageroutenode;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description: 随访计划执行列表查询返回视图类
|
||||
* @author: haown
|
||||
* @create: 2024-11-01 16:58
|
||||
**/
|
||||
@ApiModel("随访计划执行列表查询返回视图类")
|
||||
@Data
|
||||
public class PatientFollowUpPlanVo {
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 患者主键
|
||||
*/
|
||||
@ApiModelProperty(value = "患者主键")
|
||||
private Long patientId;
|
||||
|
||||
/** 所属科室id */
|
||||
@ApiModelProperty(value = "所属科室id")
|
||||
private Long departmentId;
|
||||
|
||||
/** 所属科室名称 */
|
||||
@ApiModelProperty(value = "所属科室名称")
|
||||
private String departmentName;
|
||||
|
||||
/**
|
||||
* 主治医生id
|
||||
*/
|
||||
@ApiModelProperty(value = "主治医生id")
|
||||
private Long attendingPhysicianId;
|
||||
|
||||
/**
|
||||
* 主治医生姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "主治医生姓名")
|
||||
private String attendingPhysicianName;
|
||||
|
||||
/**
|
||||
* 任务执行状态(1:完成,0:未完成)
|
||||
*/
|
||||
@ApiModelProperty(value = "任务执行状态")
|
||||
private Integer taskFinishStatus;
|
||||
|
||||
/**
|
||||
* 任务执行月份
|
||||
*/
|
||||
@ApiModelProperty(value = "任务执行月份")
|
||||
private String executeMonthStr;
|
||||
}
|
||||
@ -501,4 +501,32 @@
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
<select id="getVisitPatientList" resultType="com.xinelu.manage.vo.patientvisitrecord.PatientVisitRecordStatisticVo">
|
||||
select hospital_agency_id, hospital_agency_name, campus_agency_id, campus_agency_name,
|
||||
department_id, department_name, ward_id, ward_name,
|
||||
attending_physician_id,attending_physician_name,
|
||||
date_format(discharge_time, '%Y-%m') as dischargeTimeMonthStr
|
||||
from patient_visit_record
|
||||
<where>
|
||||
del_flag = 0
|
||||
<if test="hospitalAgencyId != null">
|
||||
and hospital_agency_id = #{hospitalAgencyId}
|
||||
</if>
|
||||
<if test="campusAgencyId != null">
|
||||
and campus_agency_id = #{campusAgencyId}
|
||||
</if>
|
||||
<if test="departmentId != null">
|
||||
and department_id = #{departmentId}
|
||||
</if>
|
||||
<if test="wardId != null">
|
||||
and ward_id = #{wardId}
|
||||
</if>
|
||||
<if test="startDate != null">
|
||||
and date_format(discharge_time,'%y%m') >= date_format(#{startDate},'%y%m')
|
||||
</if>
|
||||
<if test="endDate != null">
|
||||
and date_format(discharge_time,'%y%m') <= date_format(#{endDate},'%y%m')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
@ -20,6 +20,9 @@
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="ctUuid" column="ct_uuid"/>
|
||||
<result property="phoneDialRecordVideo" column="phone_dial_record_video"/>
|
||||
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectPhoneDialRecordVo">
|
||||
@ -37,7 +40,9 @@
|
||||
create_by,
|
||||
create_time,
|
||||
update_by,
|
||||
update_time
|
||||
update_time,
|
||||
ct_uuid,
|
||||
phone_dial_record_video
|
||||
from phone_dial_record
|
||||
</sql>
|
||||
|
||||
@ -115,6 +120,10 @@
|
||||
</if>
|
||||
<if test="updateTime != null">update_time,
|
||||
</if>
|
||||
<if test="ctUuid != null">ct_uuid,
|
||||
</if>
|
||||
<if test="phoneDialRecordVideo != null">phone_dial_record_video,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="patientId != null">#{patientId},
|
||||
@ -145,6 +154,10 @@
|
||||
</if>
|
||||
<if test="updateTime != null">#{updateTime},
|
||||
</if>
|
||||
<if test="ctUuid != null">#{ctUuid},
|
||||
</if>
|
||||
<if test="phoneDialRecordVideo != null">#{phoneDialRecordVideo},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
@ -244,4 +257,10 @@
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="getLastRecord" parameterType="java.lang.Long" resultMap="PhoneDialRecordResult">
|
||||
<include refid="selectPhoneDialRecordVo"/>
|
||||
where manage_route_node_id = #{manageRouteNodeId}
|
||||
order by dial_time desc limit 1
|
||||
</select>
|
||||
</mapper>
|
||||
@ -336,7 +336,8 @@
|
||||
spmrn.script_info_id,
|
||||
spmrn.follow_template_id,
|
||||
spmrn.node_execute_status,
|
||||
spmrn.route_handle_remark
|
||||
spmrn.route_handle_remark,
|
||||
spmrn.phone_dial_method
|
||||
FROM
|
||||
sign_patient_manage_route spmr
|
||||
LEFT JOIN sign_patient_manage_route_node spmrn ON spmr.id = spmrn.manage_route_id
|
||||
@ -396,6 +397,10 @@
|
||||
<if test="phoneNodeExecuteResultStatus = null">
|
||||
AND (spmrn.phone_node_execute_result_status is null or spmrn.phone_node_execute_result_status = ' ')
|
||||
</if>
|
||||
<if test="phoneDialMethod != null">
|
||||
AND spmrn.phone_dial_method = #{phoneDialMethod}
|
||||
</if>
|
||||
|
||||
<!-- 数据范围过滤 -->
|
||||
${params.dataScope}
|
||||
</where>
|
||||
|
||||
@ -1001,4 +1001,37 @@
|
||||
AND spmrn.route_check_status = 'AGREE'
|
||||
AND spmrn.task_node_type in ('PHONE_OUTBOUND','QUESTIONNAIRE_SCALE')
|
||||
</select>
|
||||
<select id="getFollowUpPlan" resultType="com.xinelu.manage.vo.signpatientmanageroutenode.PatientFollowUpPlanVo">
|
||||
SELECT task.manage_route_node_id as id,
|
||||
task.id as PatientId,
|
||||
task.hospital_agency_id,
|
||||
task.hospital_agency_name,
|
||||
task.department_id,
|
||||
task.department_name,
|
||||
task.attending_physician_id,
|
||||
task.attending_physician_name,
|
||||
task.task_finish_status,
|
||||
date_format(task.execute_date_time, '%Y-%m') as executeMonthStr
|
||||
from patient_task_view task
|
||||
<where>
|
||||
<if test="hospitalAgencyId != null">
|
||||
and task.hospital_agency_id = #{hospitalAgencyId}
|
||||
</if>
|
||||
<if test="campusAgencyId != null">
|
||||
and task.campus_agency_id = #{campusAgencyId}
|
||||
</if>
|
||||
<if test="departmentId != null">
|
||||
and task.department_id = #{departmentId}
|
||||
</if>
|
||||
<if test="wardId != null">
|
||||
and task.ward_id = #{wardId}
|
||||
</if>
|
||||
<if test="startDate != null">
|
||||
and task.date_format(execute_date_time,'%y%m') >= date_format(#{startDate},'%y%m')
|
||||
</if>
|
||||
<if test="endDate != null">
|
||||
and task.date_format(execute_date_time,'%y%m') <= date_format(#{endDate},'%y%m')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
@ -58,7 +58,6 @@ public class GenerateChildRouteTask {
|
||||
childSpecialRoutes.forEach(specialDiseaseRoute -> {
|
||||
// 查询路径是否生成过任务
|
||||
manageRouteQuery.setTaskCreateType(TaskCreateTypeConstant.MANUAL_MATCHE);
|
||||
manageRouteQuery.setRouteId(specialDiseaseRoute.getId());
|
||||
manageRouteQuery.setParentRouteId(signPatientManageRoute.getId());
|
||||
List<SignPatientManageRoute> createManageRouteList = signPatientManageRouteMapper.selectSignPatientManageRouteList(manageRouteQuery);
|
||||
if (CollectionUtils.isEmpty(createManageRouteList)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user