陈昶聿
9 天以前 7712550e92054c8d3a672503d6d0cf0483b2c33b
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java
@@ -867,10 +867,10 @@
                return "再次随访任务创建失败,找不到对应任务 taskid = " + serviceSubtask.getTaskid() + ", 再请次重试";
            }
            // nexttaskflag=0 表示任务链终止,不允许再生成
            if ("0".equals(serviceTask.getNexttaskflag())) {
                log.info("无需再次随访,任务已标记无后续随访, taskid = {}", serviceSubtask.getTaskid());
                return "无需再次随访,该任务无后续随访安排";
            }
//            if ("0".equals(serviceTask.getNexttaskflag())) {
//                log.info("无需再次随访,任务已标记无后续随访, taskid = {}", serviceSubtask.getTaskid());
//                return "无需再次随访,该任务无后续随访安排";
//            }
            // 幂等校验:同一原任务只允许生成一条二次随访
            ServiceSubtaskEntity againQuery = new ServiceSubtaskEntity();
            againQuery.setUpid(serviceSubtask.getId().intValue());
@@ -970,6 +970,18 @@
                return "再次随访任务创建失败,患者出院记录不完整或下一任务配置异常, 再请次重试";
            }
            Date now = new Date();
            applyAgainVisitTime(serviceSubtaskAgain, serviceSubtask, nextServiceTask, config, now);
            // 医生处理意见取自本次请求,按下一任务重建子任务时需显式带入,否则不会落库
            if (request != null) {
                serviceSubtaskAgain.setDoctorOpinion(request.getDoctorOpinion());
                serviceSubtaskAgain.setRemark(request.getRemark());
                serviceSubtaskAgain.setDrcode(request.getDrcode());
                serviceSubtaskAgain.setDrname(request.getDrname());
                serviceSubtaskAgain.setNurseId(request.getNurseId());
                serviceSubtaskAgain.setNurseName(request.getNurseName());
                serviceSubtaskAgain.setManagementDoctor(request.getManagementDoctor());
                serviceSubtaskAgain.setManagementDoctorCode(request.getManagementDoctorCode());
            }
            serviceSubtaskAgain.setId(null);
            serviceSubtaskAgain.setUpid(serviceSubtask.getId().intValue());
            serviceSubtaskAgain.setVisitCount(ObjectUtils.isNotEmpty(serviceSubtask.getVisitCount())
@@ -978,9 +990,6 @@
            serviceSubtaskAgain.setIsVisitAgain(1);
            serviceSubtaskAgain.setCreateTime(now);
            serviceSubtaskAgain.setUpdateTime(now);
            // 二次随访时间:上次随访完成时间(未完成则当前时间)+ 下一任务发送天数;过去时间兜底为当前时间
            applyAgainVisitTime(serviceSubtaskAgain, serviceSubtask, nextServiceTask, config, now);
            // 新任务的随访方式记录本次选择的再次随访方式;resource 本身不落库
            serviceSubtaskAgain.setVisitType(resource);
            serviceSubtaskAgain.setVisitDeptCode(visitDeptCode);
@@ -1058,6 +1067,10 @@
        if (dueTime.before(now)) {
            dueTime = now;
        }
        if(ObjectUtils.isNotEmpty(origin.getVisitTime())){
            dueTime = ObjectUtils.isNotEmpty(origin.getVisitTime()) ? origin.getVisitTime() : now;
        }
        target.setLongSendTime(dueTime);
        Date visitTime = dueTime;
        if ("3".equals(nextTask.getType())) {
@@ -5926,6 +5939,184 @@
        }
    }
    /**
     * 微信公众号已领取未填写:按题目默认选项补齐当前子任务,并将当前子任务完成。
     * <p>
     * 所有查询、明细写入、状态更新都只使用当前 subid,避免影响其他任务/子任务。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean completeWechatClaimedByDefault(ServiceSubtask serviceSubtask) {
        if (serviceSubtask == null || serviceSubtask.getId() == null) {
            return false;
        }
        // 重新读取当前子任务,所有判断只针对这一个 subid
        ServiceSubtask current = serviceSubtaskMapper.selectServiceSubtaskById(serviceSubtask.getId());
        if (current == null) {
            return false;
        }
        // 只处理:丽水中医院、问卷、当前方式公众号、已领取、未提交
        // 其他医院 orgid 不匹配时直接返回 false,继续走原补偿逻辑。
        if (!IServiceSubtaskService.WECHAT_DEFAULT_COMPLETE_ORGID.equals(current.getOrgid())
                || !"2".equals(current.getType())
                || !"5".equals(current.getCurrentPreachform())
                || !Long.valueOf(1L).equals(current.getSendstate())
                || Long.valueOf(1L).equals(current.getSubmit())) {
            return false;
        }
        // 查询当前子任务自己的公众号发送方式,必须是已发送(2)或已领取(3)
        ServiceSubtaskPreachform query = new ServiceSubtaskPreachform();
        query.setSubid(current.getId());
        query.setTaskid(current.getTaskid());
        query.setPreachform("5");
        List<ServiceSubtaskPreachform> preachforms = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(query);
        if (CollectionUtils.isEmpty(preachforms)) {
            return false;
        }
        ServiceSubtaskPreachform currentPreachform = preachforms.stream()
                .filter(item -> "2".equals(item.getSendstate()) || "3".equals(item.getSendstate()))
                .findFirst().orElse(null);
        if (currentPreachform == null) {
            return false;
        }
        // 只给当前 subid 补齐默认选项;至少有一题默认选项才继续
        int filled = fillWechatDefaultDetailForCurrentSubtask(current);
        if (filled <= 0) {
            log.info("【微信公众号默认完成】subid:{} 没有可填充的默认选项,跳过", current.getId());
            return false;
        }
        // 当前公众号发送方式:已发送/已领取 -> 完成(9)
        ServiceSubtaskPreachform updatePreachform = new ServiceSubtaskPreachform();
        updatePreachform.setId(currentPreachform.getId());
        updatePreachform.setSubid(current.getId());
        updatePreachform.setPreachform("5");
        updatePreachform.setOrgid(current.getOrgid());
        updatePreachform.setRemark("已领取未填写,按默认选项完成");
        int preachformUpdated = serviceSubtaskPreachformMapper.updateWechatPreachformComplete(updatePreachform);
        if (preachformUpdated == 0) {
            throw new BaseException("微信公众号默认完成失败:发送方式状态已变化,subid=" + current.getId());
        }
        // 当前子任务:已领取(1) -> 完成(6),只更新这一个 subid
        ServiceSubtask complete = new ServiceSubtask();
        complete.setId(current.getId());
        complete.setOrgid(current.getOrgid());
        complete.setFinishtime(new Date());
        complete.setResult("success");
        complete.setRemark("已领取未填写,按默认选项完成");
        int subtaskUpdated = serviceSubtaskMapper.updateWechatDefaultComplete(complete);
        if (subtaskUpdated == 0) {
            throw new BaseException("微信公众号默认完成失败:子任务状态已变化,subid=" + current.getId());
        }
        log.info("【微信公众号默认完成】subid:{},已按默认选项完成,填充题目数:{}", current.getId(), filled);
        return true;
    }
    /**
     * 仅给当前子任务补齐问卷单选/多选题中 default_value=2 的选项。
     * 已有非空答案的题目跳过,不覆盖患者已填写内容。
     *
     * @return 实际填充(或此前已由系统默认填充)的题目数
     */
    private int fillWechatDefaultDetailForCurrentSubtask(ServiceSubtask serviceSubtask) {
        Long templateId = serviceSubtask.getTemplateid();
        ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
        if (templateId == null && serviceTask != null) {
            templateId = serviceTask.getTemplateid();
        }
        if (templateId == null) {
            return 0;
        }
        SvyTaskTemplateScript scriptQuery = new SvyTaskTemplateScript();
        scriptQuery.setTemplateID(templateId);
        List<SvyTaskTemplateScript> scripts = svyTaskTemplateScriptService.selectSvyTaskTemplateScriptList(scriptQuery);
        if (CollectionUtils.isEmpty(scripts)) {
            return 0;
        }
        int filled = 0;
        for (SvyTaskTemplateScript script : scripts) {
            SvyTaskTemplateScriptVO scriptVO = DtoConversionUtils.sourceToTarget(script, SvyTaskTemplateScriptVO.class);
            SvyTaskTemplateScriptVO scriptWithOptions = svyTaskTemplateScriptService.selectInfoByCondition(scriptVO);
            if (scriptWithOptions == null
                    || scriptWithOptions.getId() == null
                    || CollectionUtils.isEmpty(scriptWithOptions.getSvyTaskTemplateTargetoptions())
                    || (!"1".equals(scriptWithOptions.getScriptType()) && !"2".equals(scriptWithOptions.getScriptType()))) {
                continue;
            }
            List<SvyTaskTemplateTargetoption> options = scriptWithOptions.getSvyTaskTemplateTargetoptions();
            List<SvyTaskTemplateTargetoption> defaultOptions = options.stream()
                    .filter(option -> option.getDefaultValue() != null && option.getDefaultValue() == 2L)
                    .filter(option -> StringUtils.isNotBlank(option.getOptioncontent()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(defaultOptions)) {
                continue;
            }
            // 已有非空答案则不覆盖,避免影响患者已填写内容
            ServiceSubtaskDetail detailQuery = new ServiceSubtaskDetail();
            detailQuery.setSubId(serviceSubtask.getId());
            detailQuery.setScriptid(scriptWithOptions.getId());
            List<ServiceSubtaskDetail> existingDetails = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(detailQuery);
            ServiceSubtaskDetail existing = CollectionUtils.isNotEmpty(existingDetails) ? existingDetails.get(0) : null;
            if (existing != null
                    && (StringUtils.isNotBlank(existing.getAsrtext()) || StringUtils.isNotBlank(existing.getMatchedtext()))) {
                // 之前已由系统默认填充过的,计入已填充,保证重试幂等
                if ("DEFAULT".equals(existing.getOperate())) {
                    filled++;
                }
                continue;
            }
            String targetValue = options.stream()
                    .map(SvyTaskTemplateTargetoption::getOptioncontent)
                    .filter(StringUtils::isNotBlank)
                    .collect(Collectors.joining("&"));
            String defaultValue = defaultOptions.stream()
                    .map(SvyTaskTemplateTargetoption::getOptioncontent)
                    .collect(Collectors.joining("&"));
            ServiceSubtaskDetail detail = new ServiceSubtaskDetail();
            detail.setSubId(serviceSubtask.getId());
            detail.setTaskid(serviceSubtask.getTaskid());
            detail.setPatid(serviceSubtask.getPatid());
            detail.setScriptid(scriptWithOptions.getId());
            detail.setTemplatequestionnum(scriptWithOptions.getId());
            detail.setQuestiontext(scriptWithOptions.getScriptContent());
            detail.setCategoryid(scriptWithOptions.getCategoryid());
            detail.setTargetid(scriptWithOptions.getTargetid() != null ? scriptWithOptions.getTargetid().intValue() : null);
            detail.setValueType(scriptWithOptions.getScriptType());
            detail.setTargetvalue(targetValue);
            detail.setAsrtext(defaultValue);
            detail.setMatchedtext(defaultValue);
            detail.setOperate("DEFAULT");
            detail.setTemplateType(2);
            detail.setLibTemplateid(serviceSubtask.getLibtemplateid() != null ? serviceSubtask.getLibtemplateid().intValue() : null);
            detail.setTemplateid(templateId.toString());
            detail.setGuid(scriptWithOptions.getGuid());
            detail.setOrgid(StringUtils.isNotEmpty(scriptWithOptions.getOrgid()) ? scriptWithOptions.getOrgid()
                    : (serviceTask != null ? serviceTask.getOrgid() : null));
            detail.setCreateTime(new Date());
            detail.setUpdateTime(new Date());
            if (existing != null) {
                detail.setId(existing.getId());
                serviceSubtaskDetailMapper.updateServiceSubtaskDetail(detail);
            } else {
                serviceSubtaskDetailMapper.insertServiceSubtaskDetail(detail);
            }
            filled++;
        }
        return filled;
    }
    @Override
    public Map<String, Object> getHeLibraryCount(@RequestBody HeLibraryCountVO heLibraryCountVO) {
        if (ObjectUtils.isEmpty(heLibraryCountVO)) {