diff --git a/postdischarge-admin/src/main/resources/application.yml b/postdischarge-admin/src/main/resources/application.yml index deba8944..4d2cdffd 100644 --- a/postdischarge-admin/src/main/resources/application.yml +++ b/postdischarge-admin/src/main/resources/application.yml @@ -30,6 +30,8 @@ xinelu: rich-text-picture-url: /richTextPictureUrl # 资讯富文本的上传路径 info-rich-text-picture-url: /infoRichTextPictureUrl + # 资讯富文本的上传路径 + phone-dial-record-video: /phoneDialRecordVideo # 开发环境配置 server: diff --git a/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java b/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java index fcedd444..9f711fef 100644 --- a/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java +++ b/postdischarge-common/src/main/java/com/xinelu/common/config/SystemBusinessConfig.java @@ -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; + } } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/agency/AgencyController.java b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/agency/AgencyController.java index 1683dc54..f5ea9908 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/agency/AgencyController.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/agency/AgencyController.java @@ -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)); } /** diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/aibo/AIOBController.java b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/aibo/AIOBController.java index 9bd62040..ee23d30d 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/aibo/AIOBController.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/aibo/AIOBController.java @@ -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"); + } } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroute/SignPatientManageRouteController.java b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroute/SignPatientManageRouteController.java index cc4d163c..65011dee 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroute/SignPatientManageRouteController.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroute/SignPatientManageRouteController.java @@ -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 createActualTimeTask(@RequestBody CreateAiboActualTimeTaskDto createAiboActualTimeTaskDto) { + Long memberId = signPatientManageRouteService.createActualTimeTask(createAiboActualTimeTaskDto); + return memberId != null && memberId > 0L ? R.ok() : R.fail(); + } + /** * 查询人工随访患者基本信息 */ diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroutenode/SignPatientManageRouteNodeController.java b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroutenode/SignPatientManageRouteNodeController.java index 12a88603..9deae987 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroutenode/SignPatientManageRouteNodeController.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/controller/signpatientmanageroutenode/SignPatientManageRouteNodeController.java @@ -130,6 +130,15 @@ public class SignPatientManageRouteNodeController extends BaseController { return R.ok(signNodeService.getSpecialDiseaseNode(patientTaskDto)); } + /** + * AI通话获取录音 + */ + @ApiOperation("AI通话获取录音") + @GetMapping("/getPhoneDialVideo/{id}") + public R getPhoneDialVideo(@PathVariable("id") Long id) { + return R.ok(signNodeService.getPhoneDialVideo(id)); + } + /** * 测试生成患者档案列表数据用 */ diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/domain/phonedialrecord/PhoneDialRecord.java b/postdischarge-manage/src/main/java/com/xinelu/manage/domain/phonedialrecord/PhoneDialRecord.java index b0690f05..2b0605e2 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/domain/phonedialrecord/PhoneDialRecord.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/domain/phonedialrecord/PhoneDialRecord.java @@ -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() { diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/domain/signpatientmanageroutenode/SignPatientManageRouteNode.java b/postdischarge-manage/src/main/java/com/xinelu/manage/domain/signpatientmanageroutenode/SignPatientManageRouteNode.java index 03ee08a5..1e5adaed 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/domain/signpatientmanageroutenode/SignPatientManageRouteNode.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/domain/signpatientmanageroutenode/SignPatientManageRouteNode.java @@ -409,4 +409,5 @@ public class SignPatientManageRouteNode extends BaseEntity { @ApiModelProperty(value = "第三方返回的任务ID") private String taskIdExt; + } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/dto/manualfollowup/ManualFollowUpDTO.java b/postdischarge-manage/src/main/java/com/xinelu/manage/dto/manualfollowup/ManualFollowUpDTO.java index a6bbe58e..6c1d2cfe 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/dto/manualfollowup/ManualFollowUpDTO.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/dto/manualfollowup/ManualFollowUpDTO.java @@ -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; } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/dto/signpatientmanageroutenode/CreateAiboActualTimeTaskDto.java b/postdischarge-manage/src/main/java/com/xinelu/manage/dto/signpatientmanageroutenode/CreateAiboActualTimeTaskDto.java new file mode 100644 index 00000000..15463f4a --- /dev/null +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/dto/signpatientmanageroutenode/CreateAiboActualTimeTaskDto.java @@ -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; +} diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/dto/statistics/FollowUpRateDto.java b/postdischarge-manage/src/main/java/com/xinelu/manage/dto/statistics/FollowUpRateDto.java index e814f29b..6919408d 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/dto/statistics/FollowUpRateDto.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/dto/statistics/FollowUpRateDto.java @@ -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; + } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/patientvisitrecord/PatientVisitRecordMapper.java b/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/patientvisitrecord/PatientVisitRecordMapper.java index 029ac569..0a8ba9da 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/patientvisitrecord/PatientVisitRecordMapper.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/patientvisitrecord/PatientVisitRecordMapper.java @@ -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 getVisitPatientList(FollowUpRateDto queryDto); + } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/phonedialrecord/PhoneDialRecordMapper.java b/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/phonedialrecord/PhoneDialRecordMapper.java index 57fc173b..5bfec274 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/phonedialrecord/PhoneDialRecordMapper.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/phonedialrecord/PhoneDialRecordMapper.java @@ -61,4 +61,6 @@ public interface PhoneDialRecordMapper { int deletePhoneDialRecordByIds(Long[] ids); List getPhoneDialStatistic(FollowUpRateDto queryDto); + + PhoneDialRecord getLastRecord(Long manageRouteNodeId); } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.java b/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.java index 339a8bd7..3cf45002 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/mapper/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.java @@ -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 selectNodeExecuteStatus(); + + List getFollowUpPlan(FollowUpRateDto queryDto); } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/IAgencyService.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/IAgencyService.java index 5d93459b..821755b4 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/IAgencyService.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/IAgencyService.java @@ -40,7 +40,7 @@ public interface IAgencyService { * @param agency 机构信息 * @return 机构信息集合 */ - AjaxResult selectAgencyByIdList(Agency agency); + List selectAgencyByIdList(Agency agency); /** * 新增机构信息 diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/impl/AgencyServiceImpl.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/impl/AgencyServiceImpl.java index 87f4a47c..3fde3ed1 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/impl/AgencyServiceImpl.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/agency/impl/AgencyServiceImpl.java @@ -101,7 +101,7 @@ public class AgencyServiceImpl implements IAgencyService { * @return 机构信息 */ @Override - public AjaxResult selectAgencyByIdList(Agency agency) { + public List selectAgencyByIdList(Agency agency) { // 查询用户角色 List 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); } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/IAIOBService.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/IAIOBService.java index 4fb0d1a1..eac8f944 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/IAIOBService.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/IAIOBService.java @@ -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); } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/impl/AIOBServiceImpl.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/impl/AIOBServiceImpl.java index 2d9d27fb..ad981840 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/impl/AIOBServiceImpl.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/aibo/impl/AIOBServiceImpl.java @@ -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 requestEntity = new HttpEntity<>(null, headers); + RestTemplate restTemplate = new RestTemplate(); + Map params = new HashMap<>(); + params.put("contactUuid", ccUUID); + params.put("expiration", 1800); + params.put("operation", 3); + ResponseEntity 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 questionSubjectOptions = questionSubjectOptionMapper.selectQuestionSubjectOptionList(questionSubjectOptionQuery); + List 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; + } } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/ISignPatientManageRouteService.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/ISignPatientManageRouteService.java index ba2ae9bb..39f1e4ea 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/ISignPatientManageRouteService.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/ISignPatientManageRouteService.java @@ -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 selectManualFollowUpList(ManualFollowUpDTO manualFollowUpDTO); + /** + * @description 随访待办列表-创建实时呼叫任务 + * @Param createAiboActualTimeTaskDto 创建百度外呼实时任务传输对象 + * @return 结果 + * @Author haown + * @Date 2024-11-4 16:06 + */ + Long createActualTimeTask(@RequestBody CreateAiboActualTimeTaskDto createAiboActualTimeTaskDto); + /** * 查询人工随访患者基本信息 * @param id 签约患者管理任务表id diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/impl/SignPatientManageRouteServiceImpl.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/impl/SignPatientManageRouteServiceImpl.java index f956f56b..4e9c53bb 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/impl/SignPatientManageRouteServiceImpl.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroute/impl/SignPatientManageRouteServiceImpl.java @@ -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 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 labelFieldContentList = labelFieldContentMapper.selectByPatientId(patientInfo.getId()); + // 处理变量 + JSONObject jsonObject = new JSONObject(); + if (com.xinelu.common.utils.StringUtils.isNotBlank(scriptInfo.getVariables())) { + List 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 diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/ISignPatientManageRouteNodeService.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/ISignPatientManageRouteNodeService.java index 2f4007db..07d0f716 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/ISignPatientManageRouteNodeService.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/ISignPatientManageRouteNodeService.java @@ -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 getSpecialDiseaseNode(PatientTaskDto patientTaskDto); + String getPhoneDialVideo(Long id); + /** * 根据参数列表修改任务 * @param paramsCurrentLists 参数列表 diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/impl/SignPatientManageRouteNodeServiceImpl.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/impl/SignPatientManageRouteNodeServiceImpl.java index 419a84dd..d9de5ba1 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/impl/SignPatientManageRouteNodeServiceImpl.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/signpatientmanageroutenode/impl/SignPatientManageRouteNodeServiceImpl.java @@ -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 diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/service/statistics/impl/StatisticsServiceImpl.java b/postdischarge-manage/src/main/java/com/xinelu/manage/service/statistics/impl/StatisticsServiceImpl.java index 4af6aacb..8012abf4 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/service/statistics/impl/StatisticsServiceImpl.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/service/statistics/impl/StatisticsServiceImpl.java @@ -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 getFollowUpDetail(FollowUpRateDto queryDto) { - return null; + List retList = new ArrayList<>(); + FollowUpDetailVo followUpDetailVo = new FollowUpDetailVo(); + // 总计行预留位置 + retList.set(0, followUpDetailVo); + // 就诊患者列表查询 + List patientVisitList = patientVisitRecordMapper.getVisitPatientList(queryDto); + // 随访计划列表查询 + List planList = signPatientManageRouteNodeMapper.getFollowUpPlan(queryDto); + + if (StringUtils.equals(queryDto.getType(), "dept")) { + // 就诊患者列表按照科室分组 + Map> groupByDept = new HashMap<>(); + if (CollectionUtils.isNotEmpty(patientVisitList)) { + groupByDept = patientVisitList.stream().collect(Collectors.groupingBy(PatientVisitRecordStatisticVo::getDepartmentId)); + } + + Map> planGroupByDept = new HashMap<>(); + if (CollectionUtils.isNotEmpty(planList)) { + // 随访计划列表按照科室分组 + planGroupByDept = planList.stream().collect(Collectors.groupingBy(PatientFollowUpPlanVo::getDepartmentId)); + } + // 查询机构、科室、医生列表 + Agency agencyQuery = new Agency(); + agencyQuery.setId(queryDto.getHospitalAgencyId()); + List agencyList = agencyService.selectAgencyByIdList(agencyQuery); + for (Agency agency : agencyList) { + // 根据机构列表查询科室 + Department deptQuery = new Department(); + deptQuery.setHospitalAgencyId(agency.getId()); + deptQuery.setNodeType(NodeTypeEnum.DEPARTMENT.getInfo()); + List deptList = departmentService.selectDepartmentList(deptQuery); + for (Department dept : deptList) { + followUpDetailVo.setRowName(dept.getDepartmentName()); + // 就诊人数 + List deptVisitList = groupByDept.get(dept.getId()); + followUpDetailVo.setPatientNum(CollectionUtils.isEmpty(deptVisitList) ? 0 : groupByDept.get(dept.getId()).size()); + + // 科室统计随访计划人数、随访覆盖率、随访成功人数、随访成功率 + List deptPlanList = planGroupByDept.get(dept.getId()); + getFollowUpDetailVo(deptPlanList, followUpDetailVo); + + // 查询科室医生 + SysUser userQuery = new SysUser(); + userQuery.setHospitalAgencyId(dept.getHospitalAgencyId()); + userQuery.setDepartmentId(dept.getId()); + List userList = userService.selectUserList(userQuery); + List childrenList = new ArrayList<>(); + + Map> patientGroupByDoctor = deptVisitList.stream().collect(Collectors.groupingBy(PatientVisitRecordStatisticVo::getAttendingPhysicianId)); + Map> 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 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 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> groupByVisitDate = new HashMap<>(); + if (CollectionUtils.isNotEmpty(patientVisitList)) { + groupByVisitDate = patientVisitList.stream().collect(Collectors.groupingBy(PatientVisitRecordStatisticVo::getDischargeTimeMonthStr)); + } + + Map> 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 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> 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> 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 getTotalRow(List 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; + } } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/vo/manualfollowup/ManualFollowUpVO.java b/postdischarge-manage/src/main/java/com/xinelu/manage/vo/manualfollowup/ManualFollowUpVO.java index b498608f..4245e5fe 100644 --- a/postdischarge-manage/src/main/java/com/xinelu/manage/vo/manualfollowup/ManualFollowUpVO.java +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/vo/manualfollowup/ManualFollowUpVO.java @@ -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; } diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/vo/patientvisitrecord/PatientVisitRecordStatisticVo.java b/postdischarge-manage/src/main/java/com/xinelu/manage/vo/patientvisitrecord/PatientVisitRecordStatisticVo.java new file mode 100644 index 00000000..fc88fc74 --- /dev/null +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/vo/patientvisitrecord/PatientVisitRecordStatisticVo.java @@ -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; + +} diff --git a/postdischarge-manage/src/main/java/com/xinelu/manage/vo/signpatientmanageroutenode/PatientFollowUpPlanVo.java b/postdischarge-manage/src/main/java/com/xinelu/manage/vo/signpatientmanageroutenode/PatientFollowUpPlanVo.java new file mode 100644 index 00000000..28468fee --- /dev/null +++ b/postdischarge-manage/src/main/java/com/xinelu/manage/vo/signpatientmanageroutenode/PatientFollowUpPlanVo.java @@ -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; +} diff --git a/postdischarge-manage/src/main/resources/mapper/manage/patientvisitrecord/PatientVisitRecordMapper.xml b/postdischarge-manage/src/main/resources/mapper/manage/patientvisitrecord/PatientVisitRecordMapper.xml index 1adb7abe..694e1462 100644 --- a/postdischarge-manage/src/main/resources/mapper/manage/patientvisitrecord/PatientVisitRecordMapper.xml +++ b/postdischarge-manage/src/main/resources/mapper/manage/patientvisitrecord/PatientVisitRecordMapper.xml @@ -501,4 +501,32 @@ + \ No newline at end of file diff --git a/postdischarge-manage/src/main/resources/mapper/manage/phonedialrecord/PhoneDialRecordMapper.xml b/postdischarge-manage/src/main/resources/mapper/manage/phonedialrecord/PhoneDialRecordMapper.xml index 8e9f3741..c282cf39 100644 --- a/postdischarge-manage/src/main/resources/mapper/manage/phonedialrecord/PhoneDialRecordMapper.xml +++ b/postdischarge-manage/src/main/resources/mapper/manage/phonedialrecord/PhoneDialRecordMapper.xml @@ -20,6 +20,9 @@ + + + @@ -37,7 +40,9 @@ create_by, create_time, update_by, - update_time + update_time, + ct_uuid, + phone_dial_record_video from phone_dial_record @@ -115,6 +120,10 @@ update_time, + ct_uuid, + + phone_dial_record_video, + #{patientId}, @@ -145,6 +154,10 @@ #{updateTime}, + #{ctUuid}, + + #{phoneDialRecordVideo}, + @@ -244,4 +257,10 @@ + + \ No newline at end of file diff --git a/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroute/SignPatientManageRouteMapper.xml b/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroute/SignPatientManageRouteMapper.xml index 3521e4ce..6f5b83ef 100644 --- a/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroute/SignPatientManageRouteMapper.xml +++ b/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroute/SignPatientManageRouteMapper.xml @@ -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 @@ AND (spmrn.phone_node_execute_result_status is null or spmrn.phone_node_execute_result_status = ' ') + + AND spmrn.phone_dial_method = #{phoneDialMethod} + + ${params.dataScope} diff --git a/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.xml b/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.xml index 83b9f017..5abe1a62 100644 --- a/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.xml +++ b/postdischarge-manage/src/main/resources/mapper/manage/signpatientmanageroutenode/SignPatientManageRouteNodeMapper.xml @@ -1001,4 +1001,37 @@ AND spmrn.route_check_status = 'AGREE' AND spmrn.task_node_type in ('PHONE_OUTBOUND','QUESTIONNAIRE_SCALE') + \ No newline at end of file diff --git a/postdischarge-quartz/src/main/java/com/xinelu/quartz/task/GenerateChildRouteTask.java b/postdischarge-quartz/src/main/java/com/xinelu/quartz/task/GenerateChildRouteTask.java index 38642962..d31808df 100644 --- a/postdischarge-quartz/src/main/java/com/xinelu/quartz/task/GenerateChildRouteTask.java +++ b/postdischarge-quartz/src/main/java/com/xinelu/quartz/task/GenerateChildRouteTask.java @@ -58,7 +58,6 @@ public class GenerateChildRouteTask { childSpecialRoutes.forEach(specialDiseaseRoute -> { // 查询路径是否生成过任务 manageRouteQuery.setTaskCreateType(TaskCreateTypeConstant.MANUAL_MATCHE); - manageRouteQuery.setRouteId(specialDiseaseRoute.getId()); manageRouteQuery.setParentRouteId(signPatientManageRoute.getId()); List createManageRouteList = signPatientManageRouteMapper.selectSignPatientManageRouteList(manageRouteQuery); if (CollectionUtils.isEmpty(createManageRouteList)) {