package com.ruoyi.inhospvisit.support; import com.ruoyi.inhospvisit.domain.row.VisitInhospRow; import com.ruoyi.inhospvisit.mapper.VisitInhospMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * 随访标志位回写器 —— 统一封装"改 {@code pat_med_inhosp} 的哪个 check_flag"这件事。 * *

来源对照(@ b25c3b51)

* * * * * *
本类方法原实现行数
{@link #updateCheckFlag(VisitInhospRow, Integer, String, String)}{@code updateCheckFlag}(L1660-1684)25
{@link #setFlag}{@code writeInSubTask} 里逐处 * {@code patMedInhosp2.setXxxcheckFlag(...)} + {@code updatePatMedInhosp}—
* *

⚠️ type → 列的映射必须原样保留(含历史交叉写)

* 原 {@code updateCheckFlag} 的 switch(L1663-1679): *
 * 1 -> deptcheck_flag        2 -> wardcheck_flag       3 -> diagcheck_flag
 * 4 -> in_deptcheck_flag     5 -> in_wardcheck_flag
 * 
* 而 {@code writeInSubTask} 里回写时会根据 type 单独 set,且存在历史交叉写: * * 所以这里不统一:{@link #updateCheckFlag} 照抄原 switch; * 各调用点要写哪一列由它自己用 {@link #setFlag} 显式指定。任何"顺手统一"都是行为变更。 * *

为什么单独成类而不是塞进 VisitSubtaskFactory

* 工厂是"纯组装"(可被 A 档逐行比对);本类是"写库"。 * 混在一起会让"组装器一个副作用都没有"这个前提失效,探针也就失去意义。 */ @Slf4j @Component public class InhospFlagWriter { /** 允许回写的标志位列白名单(与 {@code VisitInhospMapper.updateFlags} 的 {@code } 一致) */ private static final Set ALLOWED_FLAG_COLUMNS = Collections.unmodifiableSet( new HashSet<>(Arrays.asList( "deptcheck_flag", "wardcheck_flag", "diagcheck_flag", "medcheck_flag", "in_deptcheck_flag", "in_wardcheck_flag", "schedulecheck_flag"))); @Autowired private VisitInhospMapper inhospMapper; /** * 统一回写标志位 —— 照抄原 {@code updateCheckFlag(PatMedInhosp, Integer type, String flagValue, String remark)}。 *

* 原实现(L1660-1684): *

     * PatMedInhosp updateObj = new PatMedInhosp();
     * updateObj.setInhospid(patMedInhosp.getInhospid());
     * switch (type) { case 1: updateObj.setDeptcheckFlag(flagValue); break; ... }
     * if (StringUtils.isNotEmpty(remark)) {
     *     updateObj.setRemark(remark + " (type=" + type + ")");
     * }
     * patMedInhospMapper.updatePatMedInhosp(updateObj);
     * 
* ⚠️ 注意两点: *
    *
  1. 它写的是 {@code remark}(不是 {@code long_task_reason})——原样保留;
  2. *
  3. remark 非空时会拼上 {@code " (type=N)"} 后缀 —— 原样保留这个格式。
  4. *
* * @param row 出入院记录(只用 inhospid) * @param type 1=离院科室 2=离院病区 3=疾病 4=入院科室 5=入院病区 * @param flagValue 要写入的标志位值 * @param remark 备注;非空时会拼 {@code " (type=N)"} 后缀后写入 remark 列 */ public void updateCheckFlag(VisitInhospRow row, Integer type, String flagValue, String remark) { String column = columnOfType(type); if (column == null) { log.warn("【出入院随访】updateCheckFlag 收到未知 type={},忽略。inhospid={}", type, row == null ? null : row.getInhospid()); return; } String finalRemark = remark; if (com.ruoyi.common.utils.StringUtils.isNotEmpty(remark)) { finalRemark = remark + " (type=" + type + ")"; } // 原实现走的是"整实体动态更新"(会顺带把 remark 写进去)。 // 这里 updateFlags 只覆盖 flag + long_task_reason,所以 remark 需要单独写。 setFlagWithRemark(row, column, flagValue, finalRemark); } /** * 只回写一个标志位(对应 {@code writeInSubTask} 里逐处 set 单个 flag 的写法)。 *

* 原实现的写法是:新建一个"只有 inhospid + 要改的 flag"的 {@code PatMedInhosp}, * 再调 {@code updatePatMedInhosp}(XML 里每个字段各自 {@code }, * 所以只有非 null 字段生效)。 * * @param inhospid 出入院记录ID * @param column 标志位列名(白名单校验) * @param value 标志位值 * @return true = 影响行数 > 0 */ public boolean setFlag(Long inhospid, String column, String value) { if (!ALLOWED_FLAG_COLUMNS.contains(column)) { log.warn("【出入院随访】setFlag 收到非法列名「{}」,忽略。inhospid={}", column, inhospid); return false; } return inhospMapper.updateFlags(inhospid, column, value, null) > 0; } /** * 回写标志位 + 覆盖式写 {@code long_task_reason}。 *

* 对应 {@code writeInSubTask} 里"任务不存在"/"异常"分支的写法: * 先 {@code setLongTaskReason(旧值 + 文案)} 再 update。 * 注意:那些分支在 Java 侧是 {@code longTaskReason + "..."} 的字符串拼接 * (多数不判 null),所以这里由调用方传入拼好的完整值。 * * @param inhospid 出入院记录ID * @param column 标志位列名 * @param value 标志位值 * @param reason {@code long_task_reason} 的新值;null = 不改动 */ public boolean setFlagWithReason(Long inhospid, String column, String value, String reason) { if (!ALLOWED_FLAG_COLUMNS.contains(column)) { log.warn("【出入院随访】setFlagWithReason 收到非法列名「{}」,忽略。inhospid={}", column, inhospid); return false; } return inhospMapper.updateFlags(inhospid, column, value, reason) > 0; } /** * 标志位列 + remark 一起写(原 {@code updateCheckFlag} 的实际效果)。 *

* {@code VisitInhospMapper.updateFlags} 不覆盖 remark,所以这里复用它写 flag, * 另外单独更新 remark —— 两个 update 与原实现的"一次整实体 update"在结果上等价 * (原实现也只会有 flag 与 remark 两个字段非 null)。 */ /** * 回写标志位 + 覆盖式写 {@code remark}(原 {@code updateCheckFlag} 的实际效果)。 *

* {@code VisitInhospMapper.updateFlags} 不覆盖 remark,所以这里复用它写 flag, * 另外单独更新 remark —— 两个 update 与原实现的"一次整实体 update"在结果上等价 * (原实现那次调用也只有 flag 与 remark 两个字段非 null)。 * * @param inhospid 出入院记录ID * @param column 标志位列名(白名单校验) * @param flagValue 标志位值 * @param remark 新的 remark;null 表示只写 flag */ public void setFlagWithRemark(Long inhospid, String column, String flagValue, String remark) { if (!ALLOWED_FLAG_COLUMNS.contains(column)) { log.warn("【出入院随访】setFlagWithRemark 收到非法列名「{}」,忽略。inhospid={}", column, inhospid); return; } if (inhospid == null) { log.warn("【出入院随访】setFlagWithRemark 缺少 inhospid,忽略。column={}", column); return; } inhospMapper.updateFlags(inhospid, column, flagValue, null); if (remark != null) { inhospMapper.updateRemark(inhospid, remark); } } /** * 标志位列 + remark 一起写({@link #updateCheckFlag} 用,入参是行对象)。 */ private void setFlagWithRemark(VisitInhospRow row, String column, String flagValue, String remark) { if (row == null || row.getInhospid() == null) { log.warn("【出入院随访】setFlagWithRemark 缺少 inhospid,忽略。column={}", column); return; } setFlagWithRemark(row.getInhospid(), column, flagValue, remark); } /** * type → 标志位列。照抄原 {@code updateCheckFlag} 的 switch。 * * @return 列名;未知 type 返回 {@code null} */ private String columnOfType(Integer type) { if (type == null) { return null; } switch (type) { case 1: return "deptcheck_flag"; case 2: return "wardcheck_flag"; case 3: return "diagcheck_flag"; case 4: return "in_deptcheck_flag"; case 5: return "in_wardcheck_flag"; default: return null; } } }