陈昶聿
12 小时以前 235cf590b8ac4c77d0a9a715d026bc591d9df133
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -6,8 +6,10 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.service.IDingTalkService;
import com.ruoyi.common.dx.MessageSend;
import com.ruoyi.common.enums.MsgLSEnum;
import com.ruoyi.common.enums.ServiceFromEnum;
@@ -48,6 +50,7 @@
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -102,6 +105,9 @@
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private IDingTalkService dingTalkService;
    @Value("${localIP}")
@@ -268,6 +274,44 @@
        }
    }
    /**
     * 定时发送异常信息-景宁
     */
    public void sendExceptInfo() throws Exception {
        //1.获取发送人工号
        ServiceSubtaskDetailTraceVO subtaskDetailTraceVO = new ServiceSubtaskDetailTraceVO();
        subtaskDetailTraceVO.setHandleFlag("0");
        List<ServiceSubtaskDetailTrace> serviceSubtaskDetailTraces =
                serviceSubtaskDetailTraceService.selectServiceSubtaskDetailTtraceList(subtaskDetailTraceVO);
        // 把 dutyDeptPersonCode 整理到 list 中(如果多个人用逗号分割,则展开并去重)
        List<String> dutyDeptPersonCodeList = serviceSubtaskDetailTraces.stream()
                .map(ServiceSubtaskDetailTrace::getDutyDeptPersonCode)
                .filter(StringUtils::isNotBlank)
                .flatMap(code -> Arrays.stream(code.split(",")))
                .map(String::trim)
                .filter(StringUtils::isNotBlank).distinct()  // 去重
                .collect(Collectors.toList());
        // 获取“异常内容提醒"
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("send.except.content");
        String exceptContent = sysConfig.getConfigValue();
        // 获取“内容提醒测试人工号”
        String testPerson = sysConfigMapper.checkConfigKeyUnique("send.test.person").getConfigValue();
        if (StringUtils.isNotBlank(testPerson)) {
            String[] split = testPerson.split(",");
            if (CollectionUtils.isEmpty(dutyDeptPersonCodeList)) dutyDeptPersonCodeList = Arrays.asList(split);
            else dutyDeptPersonCodeList.addAll(Arrays.asList(split));
        }
        if (CollectionUtils.isNotEmpty(dutyDeptPersonCodeList)) {
            for (String dutyDeptPersonCode : dutyDeptPersonCodeList) {
                log.info("【sendExceptInfo】发送人工号:{}", dutyDeptPersonCode);
                String dutyDeptPerson = dingTalkService.getDingTalkUserByMobile(dutyDeptPersonCode);
                dingTalkService.sendDingTalkText(exceptContent, dutyDeptPerson);
            }
        }
    }
    /**
     * 定时处理外链的数据
@@ -285,6 +329,17 @@
        LocalDateTime tomorrowEnd = tomorrowStart.plusDays(1).minusSeconds(1);     // 明天 23:59:59
        ixhGatherPatArchiveService.getAppointRecordInfo("2", tomorrowStart, tomorrowEnd);
    }
    /**
     * 每月15号和月底,查询并处理 HIS 数据(同德,南华)
     */
    public void dealHisDataHalfMonth() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedNow = now.format(formatter);
        dealHisData(formattedNow);
    }
    /**
     * HIS数据采集
@@ -382,7 +437,7 @@
                    iIcd10Service.queryAddIcd10();
                }
                // nhfy/sltd回溯30天分段采集判断(每段最多7天)
                // nhfy/sltd回溯30天分段采集判断(每段最多4天)
                boolean isBackfill = (active.trim().equals("nhfy") || active.trim().equals("sltd")) && StringUtils.isNotBlank(todayZeroStr);
                if (isBackfill) {
                    DateTimeFormatter dateFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@@ -390,7 +445,7 @@
                    LocalDate segEndDate = todayZero.toLocalDate();
                    int segCount = 0;
                    while (!segStart.isAfter(segEndDate)) {
                        LocalDate segEnd = segStart.plusDays(6);
                        LocalDate segEnd = segStart.plusDays(3);
                        if (segEnd.isAfter(segEndDate)) {
                            segEnd = segEndDate;
                        }
@@ -423,7 +478,7 @@
                        list.add("FH0109.23");
                        list.add("FH0109.53");
                        serviceSLTDInhospReqVO.setStatusList(list);
                        log.info("【dealHisData】省立同德“预入院”采集数据入参:{}", serviceSLTDInhospReqVO);
//                        log.info("【dealHisData】省立同德“预入院”采集数据入参:{}", serviceSLTDInhospReqVO);
                        serviceSLTDHealthcareRecordService.queryHealthcareRecordList(serviceSLTDInhospReqVO);
                        log.info("【dealHisData】省立同德“预入院”結束采集数据,院区:{}", cid);
@@ -441,7 +496,7 @@
                        List<String> listStr = new ArrayList<>();
                        listStr.add("FH0109.24");
                        serviceSLTDInhospReqVO.setStatusList(listStr);
                        log.info("【dealHisData】省立同德“入院”采集数据入参:{}", serviceSLTDInhospReqVO);
//                        log.info("【dealHisData】省立同德“入院”采集数据入参:{}", serviceSLTDInhospReqVO);
                        serviceSLTDHealthcareRecordService.queryHealthcareRecordList(serviceSLTDInhospReqVO);
                        log.info("【dealHisData】省立同德“入院”結束采集数据,院区:{}", cid);
@@ -464,7 +519,7 @@
                        //预出院
                        list2.add("FH0109.25");
                        serviceSLTDInhospReqVO.setStatusList(list2);
                        log.info("【dealHisData】省立同德“出院”采集数据入参:{}", serviceSLTDInhospReqVO);
//                        log.info("【dealHisData】省立同德“出院”采集数据入参:{}", serviceSLTDInhospReqVO);
                        serviceSLTDHealthcareRecordService.queryHealthcareRecordList(serviceSLTDInhospReqVO);
                        log.info("【dealHisData】省立同德“出院”束采集数据,院区:{}", cid);
                    }
@@ -485,7 +540,7 @@
     * @param endDateStr   日期结束 yyyy-MM-dd
     */
    private void collectSegmentData(Long cid, String startDateStr, String endDateStr) {
        // 预入院
//        // 预入院
        log.info("【dealHisData】预入院开始采集数据,院区:{},时间段:{} ~ {}", cid, startDateStr, endDateStr);
        ServiceSLTDInhospReqVO reqVO = new ServiceSLTDInhospReqVO();
        reqVO.setOrgId("20001001");
@@ -847,7 +902,9 @@
                //2判断一下,当前的sort是不是等于需要执行的总个数,如果等于的话,说明是最后一个,直接将servuce_subtask的状态改成5,执行失败就行了
                Long cs = currentSort.get();
                if (cs.equals(serviceSubtaskPreachforms.size())) {
                if (cs.equals(serviceSubtaskPreachforms.size())
                        && isSubtaskDeadline(serviceSubtask, serviceSubtaskPreachforms)) {
                    serviceSubtask.setSendstate(7L);
                    serviceSubtask.setRemark("处理补偿任务,当前处理最后补偿,全部执行失败(超时)");
@@ -1012,18 +1069,17 @@
                    serviceOutPath.setCreateTime(new Date());
                    serviceOutPath.setOrgid(serviceSubtask.getOrgid());
                    iServiceOutPathService.insertServiceOutPath(serviceOutPath);
                    String url = "";
                    String format = String.format("%03X", serviceOutPath.getId());
                    serviceOutPath.setRadix(format);
                    serviceOutPath.setUpdateTime(new Date());
                    iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    //先判断一下发的是不是宣教
                    if (!"3".equals(serviceSubtask.getType())) {
                        sendMagParam.setPhone(serviceSubtask.getPhone());
                        sendMagParam.setUrl(StringUtils.isNotEmpty(req_path) ? localIP + ":" + req_path + "/wt?p=" + format : localIP + "/wt?p=" + format);
                        url = StringUtils.isNotEmpty(req_path) ? localIP + ":" + req_path + "/wt?p=" + format : localIP + "/wt?p=" + format;
                        sendMagParam.setUrl(url);
                        //如果type是语音随访的话(说明补偿发送方式中有电话随访的方式,这里的外链就地址只能用/sf)
                        if (serviceSubtask.getType().equals("1"))
                            sendMagParam.setUrl(StringUtils.isNotEmpty(req_path) ? localIP + ":" + req_path + "/sf?p=" + format : localIP + "/sf?p=" + format);
                            url = StringUtils.isNotEmpty(req_path) ? localIP + ":" + req_path + "/sf?p=" + format : localIP + "/sf?p=" + format;
                            sendMagParam.setUrl(url);
//                        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("wj.sms.template");
                        SysConfig sysConfig = new SysConfig();
@@ -1043,7 +1099,9 @@
                        HeLibrary heLibrary = heLibraryMapper.selectHeLibraryById(serviceSubtask.getLibtemplateid());
                        if (heLibrary.getHetype().equals("1")) {
                            sendMagParam.setPhone(serviceSubtask.getPhone());
                            sendMagParam.setUrl(StringUtils.isNotEmpty(req_path) ? localIP + ":" + req_path + "/xj?p=" + format : localIP + "/xj?p=" + format);
                            url = StringUtils.isNotEmpty(req_path) ? localIP + ":" + req_path + "/xj?p=" + format : localIP + "/xj?p=" + format;
                            sendMagParam.setUrl(url);
                            SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("xj.sms.template");
                            if (!Objects.isNull(sysConfig)) {
@@ -1061,6 +1119,11 @@
                        }
                    }
                    serviceOutPath.setRadix(format);
                    serviceOutPath.setUpdateTime(new Date());
                    serviceOutPath.setUrl(url);
                    iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    String isSuccess = null;
                    log.info("active的值为:{}", active);
                    if (active.equals("xh")) {
@@ -1234,6 +1297,7 @@
                    String format = String.format("%03X", serviceOutPath.getId());
                    serviceOutPath.setRadix(format);
                    serviceOutPath.setUpdateTime(new Date());
                    serviceOutPath.setUrl(url);
                    iServiceOutPathService.updateServiceOutPath(serviceOutPath);
                    //获取微信公众号请求信息根据机构ID
@@ -1362,9 +1426,9 @@
                serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                return "-1";
            }
            // 当sort等于列表size时,并且所有sendstate都不等于9,则返回-1
            if (currentSort.get().equals((long) serviceSubtaskPreachforms.size())) {
            if (currentSort.get().equals((long) serviceSubtaskPreachforms.size())
                    && isSubtaskDeadline(serviceSubtask, serviceSubtaskPreachforms)) {
                if (allSendStateNot1AndNot9) {
                    //说明全发送失败了
                    serviceSubtask.setSendstate(7L);
@@ -1520,6 +1584,47 @@
        }
    }
    public void collectHISYesterday() {
        try {
            // 获取昨天0点到今天0点的时间范围
            LocalDateTime todayZero = LocalDateTime.now().with(LocalTime.MIN);
            LocalDateTime yesterdayZero = todayZero.minusDays(1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String startTime = yesterdayZero.format(formatter);
            String endTime = todayZero.format(formatter);
            // HIS数据采集
            log.info("【collectHISYesterday】HIS开始采集数据");
            // 立即返回,后台异步执行
            CompletableFuture.runAsync(() -> {
                ichService.syncMedInhosp(startTime, endTime);
            });
            log.info("【collectHISYesterday】HIS结束采集数据");
        } catch (Exception e) {
            log.error("【collectHISYesterday】HIS数据采集异常", e);
        }
    }
    public void collectHISDaysBefore(Long daysBefore) {
        try {
            // 获取daysBefore 0点到daysBefore-1 0点的时间范围
            LocalDateTime todayZero = LocalDateTime.now().with(LocalTime.MIN);
            LocalDateTime daysBeforeZeroStart = todayZero.minusDays(daysBefore);
            LocalDateTime daysBeforeZeroEnd = todayZero.minusDays(daysBefore-1L);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String startTime = daysBeforeZeroStart.format(formatter);
            String endTime = daysBeforeZeroEnd.format(formatter);
            // HIS数据采集
            log.info("【collectHISDaysBefore】HIS开始采集数据: startTime:{}, endtime:{}",startTime, endTime);
            // 立即返回,后台异步执行
            CompletableFuture.runAsync(() -> {
                ichService.syncMedInhosp(startTime, endTime);
            });
            log.info("【collectHISDaysBefore】HIS结束采集数据: startTime:{}, endtime:{}",startTime, endTime);
        } catch (Exception e) {
            log.error("【collectHISDaysBefore】HIS数据采集异常", e);
        }
    }
    public Boolean setSuccessPreachForm(ServiceSubtask serviceSubtask, String preachform, String remark, String failSendstate) {
        if (preachform.equals("-1")) {
            //说明都不需要执行了
@@ -1548,7 +1653,7 @@
//        //人工的未发送状态,需要查2
//        if (preachform.equals("1") && StringUtils.isNotEmpty(failSendstate) && Long.valueOf(failSendstate) > 2)
//            serviceSubtaskPreachform.setSendstate("2");
        log.error("-----serviceSubtaskPreachform的入参是?{}", serviceSubtaskPreachform);
        List<ServiceSubtaskPreachform> serviceSubtaskPreachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
        if (CollectionUtils.isNotEmpty(serviceSubtaskPreachforms)) {
            ServiceSubtaskPreachform serviceSubtaskPreachform1 = serviceSubtaskPreachforms.get(0);
@@ -1561,7 +1666,8 @@
            serviceSubtaskPreachformMapper.updateServiceSubtaskPreachform(serviceSubtaskPreachform1);
            //如果当前的preachform已经是最后一个了,那直接将serviceSubtask的sendstate状态改成7就行了(全超时了)
            if (serviceSubtaskPreachform1.getSort() == sspCount.size()) {
            if (serviceSubtaskPreachform1.getSort() == sspCount.size()
                    && isSubtaskDeadline(serviceSubtask, serviceSubtaskPreachforms)) {
                if (failSendstate.equals("4") || failSendstate.equals("5")) {
                    serviceSubtask.setCurrentPreachform(preachform);
                    serviceSubtask.setSendstate(7L);
@@ -1678,4 +1784,103 @@
            log.error("【rollTaskGroupCycle】滚动调度异常", e);
        }
    }
    /**
     * 随访任务是否超时
     * @param serviceSubtask
     * @param serviceSubtaskPreachforms
     * @return
     */
    public boolean isSubtaskDeadline(ServiceSubtask serviceSubtask, List<ServiceSubtaskPreachform> serviceSubtaskPreachforms){
        if (ObjectUtils.isNotEmpty(serviceSubtask)) {
            //只有出院随访和专病随访有超时
            if(StringUtils.isNotEmpty(serviceSubtask.getServiceType()) &&
                    !serviceSubtask.getServiceType().equals("2") && !serviceSubtask.getServiceType().equals("13")){
                return true;
            }
        }
        if (Objects.isNull(serviceSubtask) || CollectionUtils.isEmpty(serviceSubtaskPreachforms)) {
            return false;
        }
        // 基准时刻:出院时间 + 发送日(sendDay 缺省按 1),并兜底避免 NPE/脏数据
        ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
        int sendDay = serviceTask != null && serviceTask.getSendDay() != null ? serviceTask.getSendDay().intValue() : 1;
        Date deadline = DateUtils.addDays(serviceSubtask.getEndtime(), sendDay);
        int sumCompensateTime = CollectionUtils.isEmpty(serviceSubtaskPreachforms) ? 0 : serviceSubtaskPreachforms.stream()
                .mapToInt(x -> x.getCompensateTime() == null ? 0 : Integer.parseInt(x.getCompensateTime()))
                .sum();
        sumCompensateTime = sumCompensateTime + 1;
        // 只补偿最后一步自身的补偿时间(天),脏值一律按 0 兜底
        deadline = DateUtils.addDays(deadline, sumCompensateTime);
        // 出院(发送)时间 + 本步补偿时间 小于当前时间 -> 超时
        return deadline.getTime() < new Date().getTime();
    }
    /**
     * 处理超时随访任务
     * @return
     */
    public void dealSubtaskDeadline(String orgid, Integer deadlineDay){
        //获取任务信息
        ServiceTask st = new ServiceTask();
        st.setDelFlag("0");
        st.setLongTask(1);
        st.setNexttaskflag("1");
        st.setOrgid(orgid);
        List<ServiceTask> serviceTasks = serviceTaskMapper.selectServiceTaskList(st);
        for (ServiceTask serviceTask : serviceTasks) {
            deadlineDay = -deadlineDay;
            Date deadline = DateUtils.addDays(new Date(), deadlineDay);
            //通过任务ID拿到患者信息,并且随访时间得是今天之前的
            ServiceSubtaskEntity serviceSubtaskVO = new ServiceSubtaskEntity();
            serviceSubtaskVO.setOrgid(orgid);
            serviceSubtaskVO.setSendstate(7L);
            //只扫描首次随访的
            serviceSubtaskVO.setVisitCount(1);
            serviceSubtaskVO.setTaskid(serviceTask.getTaskid());
            serviceSubtaskVO.setEndOutHospTime(deadline);
            List<ServiceSubtask> serviceSubtaskList
                    = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskVO);
            log.info("【dealSubtaskDeadline】获取到{}个超时任务, taskid={}", serviceSubtaskList.size(), serviceTask.getTaskid());
            for (ServiceSubtask serviceSubtask : serviceSubtaskList) {
                PatMedInhosp patMedInhospVo = new PatMedInhosp();
                patMedInhospVo.setOrgid(serviceSubtask.getOrgid());
                patMedInhospVo.setInhospid(serviceSubtask.getInhospid());
                List<PatMedInhosp> patMedInhospList = iPatMedInhospService.selectPatMedInhospList(patMedInhospVo);
                PatMedInhosp patMedInhosp = new PatMedInhosp();
                if (!patMedInhospList.isEmpty()) {
                    patMedInhosp = patMedInhospList.get(0);
                }else {
                    continue;
                }
                if(ObjectUtils.isEmpty(serviceTask.getNexttaskid())){
                    continue;
                }
                ServiceTask nextServiceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceTask.getNexttaskid());
                PatArchive patArchive = patArchiveService.selectPatArchiveByPatid(serviceSubtask.getPatid());
                String config = configService.selectConfigByKey("visit.early.day");
                Integer type = 1;
                //新增再次随访任务
                ServiceSubtask serviceSubtaskAgain = iPatMedInhospService.boxedServiceSubtask(nextServiceTask,
                        patMedInhosp, patArchive, config, type);
                serviceSubtaskAgain.setId(null);
                serviceSubtaskAgain.setUpid(serviceSubtask.getId().intValue());
                serviceSubtaskAgain.setVisitCount(serviceSubtask.getVisitCount() + 1);
                serviceSubtaskAgain.setSendstate(2L);
                serviceSubtaskAgain.setCreateTime(new Date());
                serviceSubtaskAgain.setUpdateTime(new Date());
                serviceSubtaskAgain.setVisitType(serviceSubtask.getVisitType());
                serviceSubtaskAgain.setVisitDeptCode(serviceSubtask.getVisitDeptCode());
                serviceSubtaskAgain.setVisitDeptName(serviceSubtask.getVisitDeptName());
                int i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtaskAgain);
                if (i == 1) {
                    //再次随访任务创建成功后,原任务改为失败状态
                    serviceSubtask.setSendstate(5L);
                    serviceSubtaskMapper.updateServiceSubtask(serviceSubtask);
                }
            }
        }
    }
}