liusheng
5 天以前 0bbbd746e8c39d91ad7b47a4e36e29ab972dc98c
ruoyi-inhospvisit/src/main/java/com/ruoyi/inhospvisit/service/InhospTaskOrchestrator.java
@@ -88,19 +88,29 @@
@Service
public class InhospTaskOrchestrator {
    /** 出院随访的服务类型 */
    /**
     * 出院随访的服务类型
     */
    private static final String SERVICE_TYPE_DISCHARGE = "2";
    /** 维度:科室 */
    /**
     * 维度:科室
     */
    private static final String DEPT_TYPE_DEPT = "1";
    /** 维度:病区 */
    /**
     * 维度:病区
     */
    private static final String DEPT_TYPE_WARD = "2";
    /** 站点:新华(跳过病区+疾病维度) */
    /**
     * 站点:新华(跳过病区+疾病维度)
     */
    private static final String SITE_XH = "xh";
    /** 站点:南华附一(疾病维度用诊断名) */
    /**
     * 站点:南华附一(疾病维度用诊断名)
     */
    private static final String SITE_NHFY = "nhfy";
    @Value("${spring.profiles.active}")
@@ -161,20 +171,15 @@
     * <h3>站点差异(保留)</h3>
     * {@code xh} 只做科室维度 —— {@link #addDimension} 里统一挡掉病区/疾病。
     *
     * @param inhosp 待处理的出院患者
     * @param inhosp  待处理的出院患者
     * @param archive 患者档案
     * @param rule 已查好的规则;{@code null} = 该科室/病区未配置规则
     * @param config {@code sys_config: visit.early.day}
     * @param rule    已查好的规则;{@code null} = 该科室/病区未配置规则
     * @param config  {@code sys_config: visit.early.day}
     */
    public void addSubTaskByRule(VisitInhospRow inhosp, VisitArchiveRow archive,
                                 VisitTaskRule rule, String config) {
    public void addSubTaskByRule(VisitInhospRow inhosp, VisitArchiveRow archive, VisitTaskRule rule, String config) {
        try {
            List<Integer> order = resolveDimensionOrder(rule);
            log.info("【基于规则】患者{}规则:deptRule={}, wradRule={}, diagRule={};维度尝试顺序={}",
                    inhosp.getInhospid(),
                    rule == null ? null : rule.getDeptRule(),
                    rule == null ? null : rule.getWradRule(),
                    rule == null ? null : rule.getDiagRule(), order);
            log.info("【基于规则】患者{}规则:deptRule={}, wradRule={}, diagRule={};维度尝试顺序={}", inhosp.getInhospid(), rule == null ? null : rule.getDeptRule(), rule == null ? null : rule.getWradRule(), rule == null ? null : rule.getDiagRule(), order);
            Integer hit = null;
            for (Integer type : order) {
@@ -242,7 +247,9 @@
        return order;
    }
    /** 追加一个候选维度;{@code xh} 站点只允许科室维度(原 {@code !active.equals("xh")} 的等价写法) */
    /**
     * 追加一个候选维度;{@code xh} 站点只允许科室维度(原 {@code !active.equals("xh")} 的等价写法)
     */
    private void addDimension(List<Integer> order, int type, boolean xhSite) {
        if (xhSite && type != 1) {
            return;
@@ -265,9 +272,10 @@
        }
    }
    /** 尝试一个维度,返回"是否真的生成了(或本来就已经有)一条子任务" */
    private boolean generateOneForDimension(VisitInhospRow inhosp, VisitArchiveRow archive,
                                            int type, String config) {
    /**
     * 尝试一个维度,返回"是否真的生成了(或本来就已经有)一条子任务"
     */
    private boolean generateOneForDimension(VisitInhospRow inhosp, VisitArchiveRow archive, int type, String config) {
        switch (type) {
            case 1:
                return addDeptSubTaskForPatient(inhosp, archive, config) > 0;
@@ -309,16 +317,16 @@
                continue;
            }
            if (hit == type) {
                updateCheckFlag(inhosp, type, "1", composeRemark(inhosp,
                        "按优先级生成一条随访任务(维度=" + dimensionName(type) + ")"));
                updateCheckFlag(inhosp, type, "1", composeRemark(inhosp, "按优先级生成一条随访任务(维度=" + dimensionName(type) + ")"));
            } else {
                updateCheckFlag(inhosp, type, "2", composeRemark(inhosp,
                        "已生成一条随访任务(维度=" + dimensionName(hit) + "),本维度跳过"));
                updateCheckFlag(inhosp, type, "2", composeRemark(inhosp, "已生成一条随访任务(维度=" + dimensionName(hit) + "),本维度跳过"));
            }
        }
    }
    /** 拼 reason:沿用原实现的 {@code remark + ";xxx"} 形式 */
    /**
     * 拼 reason:沿用原实现的 {@code remark + ";xxx"} 形式
     */
    private String composeRemark(VisitInhospRow inhosp, String text) {
        String remark = inhosp.getRemark();
        return StringUtils.isNotEmpty(remark) ? remark + ";" + text : text;
@@ -364,8 +372,7 @@
                u.setWardcheckFlag(fresh == null ? null : fresh.getWardcheckFlag());
                u.setDiagcheckFlag(fresh == null ? null : fresh.getDiagcheckFlag());
                // 原实现不判 null(fresh.getLongTaskReason() + "..."),原样保留
                u.setLongTaskReason((fresh == null ? null : fresh.getLongTaskReason())
                        + "该患者所在科室未配置离院长期任务;");
                u.setLongTaskReason((fresh == null ? null : fresh.getLongTaskReason()) + "该患者所在科室未配置离院长期任务;");
                updateInhosp(u);
            } else {
                for (VisitTaskdeptRow t : taskdepts) {
@@ -373,8 +380,7 @@
                    if (subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 1, config)) {
                        return 1;
                    }
                    log.info("【科室任务】患者{}任务{}未生成子任务,尝试下一个候选",
                            inhosp.getInhospid(), t.getTaskId());
                    log.info("【科室任务】患者{}任务{}未生成子任务,尝试下一个候选", inhosp.getInhospid(), t.getTaskId());
                }
            }
        } catch (Exception e) {
@@ -430,8 +436,7 @@
                u.setDeptcheckFlag(fresh == null ? null : fresh.getDeptcheckFlag());
                u.setDiagcheckFlag(fresh == null ? null : fresh.getDiagcheckFlag());
                // 原有判空(与科室维度那处不同),原样保留
                u.setLongTaskReason(StringUtils.isNotEmpty(fresh == null ? null : fresh.getLongTaskReason())
                        ? fresh.getLongTaskReason() + errorreason : errorreason);
                u.setLongTaskReason(StringUtils.isNotEmpty(fresh == null ? null : fresh.getLongTaskReason()) ? fresh.getLongTaskReason() + errorreason : errorreason);
                updateInhosp(u);
            } else {
                for (VisitTaskdeptRow t : taskdeptList) {
@@ -439,8 +444,7 @@
                    if (subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 2, config)) {
                        return 1;
                    }
                    log.info("【病区任务】患者{}任务{}未生成子任务,尝试下一个候选",
                            inhosp.getInhospid(), t.getTaskId());
                    log.info("【病区任务】患者{}任务{}未生成子任务,尝试下一个候选", inhosp.getInhospid(), t.getTaskId());
                }
            }
        } catch (Exception e) {
@@ -506,23 +510,19 @@
                int flag = 0;
                for (VisitTaskdiagRow t : taskdiags) {
                    // 原 L1975-1983:必须科室或病区能匹配上才建
                    if (StringUtils.isNotEmpty(t.getDeptCode())
                            && t.getDeptCode().equals(inhosp.getLeaveldeptcode())) {
                    if (StringUtils.isNotEmpty(t.getDeptCode()) && t.getDeptCode().equals(inhosp.getLeaveldeptcode())) {
                        flag = 1;
                        // 一个患者只留一条:第一条真正落库的即返回
                        if (subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 3, config)) {
                            return 1;
                        }
                        log.info("【疾病任务】患者{}任务{}未生成子任务,尝试下一个候选",
                                inhosp.getInhospid(), t.getTaskId());
                    } else if (StringUtils.isNotEmpty(t.getWardCode())
                            && t.getWardCode().equals(inhosp.getLeavehospitaldistrictcode())) {
                        log.info("【疾病任务】患者{}任务{}未生成子任务,尝试下一个候选", inhosp.getInhospid(), t.getTaskId());
                    } else if (StringUtils.isNotEmpty(t.getWardCode()) && t.getWardCode().equals(inhosp.getLeavehospitaldistrictcode())) {
                        flag = 1;
                        if (subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 3, config)) {
                            return 1;
                        }
                        log.info("【疾病任务】患者{}任务{}未生成子任务,尝试下一个候选",
                                inhosp.getInhospid(), t.getTaskId());
                        log.info("【疾病任务】患者{}任务{}未生成子任务,尝试下一个候选", inhosp.getInhospid(), t.getTaskId());
                    }
                }
                if (flag == 0) {
@@ -571,13 +571,11 @@
        try {
            VisitTaskCreateApi api = taskApi();
            if (api == null) {
                log.warn("【出入院随访】VisitTaskCreateApi 不可用,跳过再入院处理。inhospid={}",
                        newInHosp.getInhospid());
                log.warn("【出入院随访】VisitTaskCreateApi 不可用,跳过再入院处理。inhospid={}", newInHosp.getInhospid());
                return;
            }
            // 原 L1324-1328:patid + sendstate=2(不设 taskid)
            List<VisitPendingSubtaskDto> pendingList =
                    api.findPendingSubtasks(newInHosp.getPatid(), null);
            List<VisitPendingSubtaskDto> pendingList = api.findPendingSubtasks(newInHosp.getPatid(), null);
            if (CollectionUtils.isEmpty(pendingList)) {
                return;
            }
@@ -592,8 +590,7 @@
                    continue;
                }
                // 原 L1342-1350:旧子任务的出院时间在新入院时间之前 → 停掉
                if (pending.getEndtime() != null && newInHosp.getStarttime() != null
                        && pending.getEndtime().before(newInHosp.getStarttime())) {
                if (pending.getEndtime() != null && newInHosp.getStarttime() != null && pending.getEndtime().before(newInHosp.getStarttime())) {
                    pending.setSendstate(4L);
                    pending.setIsVisitAgain(2);
                    pending.setRemark("患者再入院");
@@ -607,7 +604,9 @@
        }
    }
    /** 景宁机构ID(原 L1338;与 InhospSubtaskWriter 里那份是同一常量,已逐字核对) */
    /**
     * 景宁机构ID(原 L1338;与 InhospSubtaskWriter 里那份是同一常量,已逐字核对)
     */
    private static final String ORG_JINGNING = "47255004333112711A1001";
    // ==========================================================================
@@ -655,13 +654,19 @@
     */
    public static class VisitTaskRule {
        /** 科室规则:"1"=首要 "2"=次要,其它=不参与 */
        /**
         * 科室规则:"1"=首要 "2"=次要,其它=不参与
         */
        private String deptRule;
        /** 病区规则(原字段名就是拼错的 {@code wradRule},保持同名以免读错) */
        /**
         * 病区规则(原字段名就是拼错的 {@code wradRule},保持同名以免读错)
         */
        private String wradRule;
        /** 疾病规则 */
        /**
         * 疾病规则
         */
        private String diagRule;
        public String getDeptRule() {
@@ -689,13 +694,16 @@
        }
    }
    /** 供测试/日志:本类是否拿到了必需的 Mapper */
    /**
     * 供测试/日志:本类是否拿到了必需的 Mapper
     */
    boolean hasMappers() {
        return inhospMapper != null && archiveMapper != null
                && taskdeptMapper != null && taskdiagMapper != null;
        return inhospMapper != null && archiveMapper != null && taskdeptMapper != null && taskdiagMapper != null;
    }
    /** 预留:供日志使用的时间戳(避免 IDE 报未使用 import Date) */
    /**
     * 预留:供日志使用的时间戳(避免 IDE 报未使用 import Date)
     */
    @SuppressWarnings("unused")
    private Date now() {
        return new Date();