| | |
| | | @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}") |
| | |
| | | * <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) { |
| | |
| | | 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; |
| | |
| | | } |
| | | } |
| | | |
| | | /** 尝试一个维度,返回"是否真的生成了(或本来就已经有)一条子任务" */ |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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) { |
| | |
| | | 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) { |
| | |
| | | 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) { |
| | |
| | | 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) { |
| | |
| | | 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) { |
| | |
| | | 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; |
| | | } |
| | |
| | | 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("患者再入院"); |
| | |
| | | } |
| | | } |
| | | |
| | | /** 景宁机构ID(原 L1338;与 InhospSubtaskWriter 里那份是同一常量,已逐字核对) */ |
| | | /** |
| | | * 景宁机构ID(原 L1338;与 InhospSubtaskWriter 里那份是同一常量,已逐字核对) |
| | | */ |
| | | private static final String ORG_JINGNING = "47255004333112711A1001"; |
| | | |
| | | // ========================================================================== |
| | |
| | | */ |
| | | public static class VisitTaskRule { |
| | | |
| | | /** 科室规则:"1"=首要 "2"=次要,其它=不参与 */ |
| | | /** |
| | | * 科室规则:"1"=首要 "2"=次要,其它=不参与 |
| | | */ |
| | | private String deptRule; |
| | | |
| | | /** 病区规则(原字段名就是拼错的 {@code wradRule},保持同名以免读错) */ |
| | | /** |
| | | * 病区规则(原字段名就是拼错的 {@code wradRule},保持同名以免读错) |
| | | */ |
| | | private String wradRule; |
| | | |
| | | /** 疾病规则 */ |
| | | /** |
| | | * 疾病规则 |
| | | */ |
| | | private String diagRule; |
| | | |
| | | public String getDeptRule() { |
| | |
| | | } |
| | | } |
| | | |
| | | /** 供测试/日志:本类是否拿到了必需的 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(); |