package com.ruoyi.common.core.service;
|
|
import com.ruoyi.common.core.service.dto.InHospPublicityRowDto;
|
import com.ruoyi.common.core.service.dto.PublicityTaskMatchDto;
|
|
import java.util.List;
|
|
/**
|
* 宣教模块所需的<b>只读/回写数据端口</b>(接口在 ruoyi-common,实现由 smartor 提供)。
|
*
|
* <h3>为什么要有这个端口</h3>
|
* 宣教模块({@code ruoyi-publicity})要做两件事:
|
* <ol>
|
* <li>查"这个科室/病区/药品有没有配长期宣教任务"({@code service_taskdept} / {@code service_taskmedical});</li>
|
* <li>扫"哪些在院患者还没做入院宣教"({@code pat_med_inhosp} 的 {@code in_deptcheck_flag} /
|
* {@code in_wardcheck_flag}),查不到患者档案时把标志位置 "2" 并追加原因。</li>
|
* </ol>
|
* 这些表和 SQL 全在 smartor。若让 {@code ruoyi-publicity} 直接依赖 smartor,
|
* 就会形成 {@code smartor ↔ ruoyi-publicity} 循环依赖(smartor 要依赖它来触发宣教)。
|
* 若把 SQL 抄一份到新模块,就会出现"同一份口径两处维护"的隐患
|
* —— 这正是满意度模块当初极力避免的坑。
|
* <p>
|
* 所以:<b>接口放 ruoyi-common,实现({@code PublicityDataPortBridge})留在 smartor</b>,
|
* 宣教模块运行时按类型查找实现。这与
|
* {@link VisitTaskCreateApi} / {@link PublicitySubtaskApi} 是同一手法。
|
*
|
* <h3>调用方务必降级</h3>
|
* 取不到实现时按"没有宣教要做"处理并打 WARN,绝不能让出入院随访主流程抛异常。
|
*/
|
public interface PublicityDataPort {
|
|
/**
|
* 扫在院患者(原 {@code patMedInhospMapper.selectPatMedInhospList} 的两段查询)。
|
* <p>
|
* 迁移对应 {@code PatMedInhospServiceImpl#dealOutHospInfo}:
|
* <ul>
|
* <li>科室维度(L325-329):{@code deptcheck_flag="0"}、{@code inhospstate="1"}、{@code fuflag="1"};</li>
|
* <li>病区维度(L376-379):{@code in_wardcheck_flag="0"}、{@code inhospstate="1"}、{@code fuflag="1"}
|
* (并把 inDeptcheckFlag / deptcheckFlag 置 null)。</li>
|
* </ul>
|
* 两段是<b>独立查询</b>,调用方分两次调(不要合并成一次"OR"查询,那会改变结果集)。
|
*
|
* @param checkFlagColumn {@code "in_deptcheck_flag"} 或 {@code "in_wardcheck_flag"}(只允许这两个值)
|
* @return 在院患者行;无数据返回空列表
|
*/
|
List<InHospPublicityRowDto> findInHospForPublicity(String checkFlagColumn);
|
|
/**
|
* 按科室/病区查长期宣教任务ID(原 {@code serviceTaskdeptMapper.selectServiceTaskdeptList})。
|
* <p>
|
* 迁移对应 L347-353({@code deptType="1"}、{@code serviceType="17"})与
|
* L390-396({@code deptType="2"}、{@code serviceType="17"})。
|
* SQL 条件:{@code del_flag = 0}、{@code longtask = 1}、{@code dept_code = ?}、
|
* {@code dept_type = ?}、{@code service_type = '17'}、{@code orgid = ?}。
|
*
|
* @param deptCode 科室编码(deptType=1)或病区编码(deptType=2)
|
* @param deptType "1" = 科室, "2" = 病区
|
* @param orgid 机构ID
|
* @param inhospid 该条记录对应的出入院记录ID(回填进返回值,方便调用方回调 inhospvisit)
|
* @return 命中的任务(可能多条);无数据返回空列表
|
*/
|
List<PublicityTaskMatchDto> findDeptPublicityTaskIds(String deptCode, String deptType,
|
String orgid, Long inhospid);
|
|
/**
|
* 按药品编码 + 名称 + 公司查长期宣教任务ID(原 {@code serviceTaskmedicalMapper.selectServiceTaskmedicalList})。
|
* <p>
|
* 迁移对应原代码 L424-434。原实现设了<b>三个</b>字段:
|
* <pre>
|
* serviceTaskmedical.setMedicalCode(split[i]);
|
* if (i < medicalCompanyArray.length) {
|
* serviceTaskmedical.setMedicalCompany(medicalCompanyArray[i]);
|
* } else {
|
* log.warn("...下标越界...");
|
* serviceTaskmedical.setMedicalName(""); // ← 注意:越界时设的是 name,不是 company
|
* }
|
* </pre>
|
* <p>
|
* ⚠️ <b>越界分支是个历史笔误,但会真实影响 SQL,因此必须原样保留</b>:
|
* 越界时 {@code medical_name} 被置为<b>空串</b>(而非 null),
|
* 而 SQL 条件是 {@code <if test="medicalName != null and medicalName != ''">} —— 空串会跳过该条件;
|
* 同时 {@code medical_company} 保持为 <b>null</b>(未被赋值),SQL 条件同样跳过。
|
* 也就是说:<b>越界时两个条件都不过滤</b>(等价于只按 medical_code 查)。
|
* <p>
|
* 所以本方法必须把 {@code medicalName} 也传进来 —— 不能让 Bridge 自作主张把空串转成 null
|
* 或反过来(那会改变 SQL 条件是否生效)。
|
*
|
* @param medicalCode 药品编码
|
* @param medicalName 药品名称;越界分支传<b>空串</b>;正常分支传 null
|
* @param medicalCompany 药品公司;越界分支传 null;正常分支传数组里的值
|
* @param inhospid 该条记录对应的出入院记录ID
|
* @return 命中的任务(可能多条);无数据返回空列表
|
*/
|
List<PublicityTaskMatchDto> findMedicalPublicityTaskIds(String medicalCode, String medicalName,
|
String medicalCompany, Long inhospid);
|
|
/**
|
* 患者档案是否存在(原 {@code patArchiveMapper.selectPatArchiveByPatid(patid)} 的判空用途)。
|
* <p>
|
* 迁移对应 L338-344 / L382-388。原实现取的是完整 {@code PatArchive},
|
* 但宣教这一层<b>只用到"是不是 null"</b>(真正的患者信息填充发生在 inhospvisit 组子任务时),
|
* 所以这里只返回存在性。
|
*
|
* @param patid 患者档案ID(即 {@code PatMedInhosp.patid} / {@code PatArchive.id},都是 Long)
|
* @return true = 存在且未删除
|
*/
|
boolean existsPatArchive(Long patid);
|
|
/**
|
* 把入院宣教的标志位置为给定值,并可同时写 {@code long_task_reason}。
|
* <p>
|
* 迁移对应 L340-342 / L357-359 / L367-370(科室维度)与 L384-386 / L400-402(病区维度)。
|
*
|
* <h3>⚠️ 原实现有"覆盖"与"追加"两种写法,必须区分(所以这里给的是 {@code reasonMode})</h3>
|
* <table border="1">
|
* <tr><th>场景</th><th>原代码</th><th>语义</th></tr>
|
* <tr><td>患者基本信息为空(科室/病区共用)</td>
|
* <td>{@code setLongTaskReason("患者基本信息为空")}</td>
|
* <td><b>覆盖</b>(直接赋值,丢掉旧值)</td></tr>
|
* <tr><td>科室未配宣教任务</td>
|
* <td>{@code setLongTaskReason(旧值 + "该患者所在科室未配置入院长期宣教任务;")}<br>
|
* 其中"旧值"是<b>按 inhospid 重查一次</b>拿到的</td>
|
* <td><b>追加</b>(且不判旧值是否为 null)</td></tr>
|
* <tr><td>病区未配宣教任务</td>
|
* <td>{@code setLongTaskReason(旧值 + "该患者所在病区未配置入院长期宣教任务;")}</td>
|
* <td><b>追加</b>(同样不判 null;旧值为 null 时会拼出 {@code "null该患者所在病区..."})</td></tr>
|
* <tr><td>科室处理异常</td>
|
* <td>{@code setLongTaskReason("人员入院科室处理出异常了")}</td>
|
* <td><b>覆盖</b>;且原代码<b>不设 longTaskReason 前缀</b>、也不重查</td></tr>
|
* </table>
|
* 因为"覆盖 / 追加"是两种不同语义,本方法用一个布尔区分,而不是让调用方拼字符串
|
* —— 拼字符串会让 {@code null} 前缀这种原缺陷被"顺手修掉",那就成了行为变更。
|
*
|
* @param inhospid 出入院记录ID
|
* @param flagColumn {@code "in_deptcheck_flag"} 或 {@code "in_wardcheck_flag"}(只允许这两个值)
|
* @param flagValue 要写入的标志位值(原实现写 "2")
|
* @param reason 要写入 {@code long_task_reason} 的文案;为 null 表示<b>不动</b>该字段
|
* @param appendMode true = 追加({@code 旧值 + reason},旧值按 inhospid 重查,<b>不判 null</b>);
|
* false = 覆盖(直接写 {@code reason})
|
* @return true = 更新成功
|
*/
|
boolean updatePublicityFlag(Long inhospid, String flagColumn, String flagValue,
|
String reason, boolean appendMode);
|
|
/**
|
* 按字段更新出入院记录(可一次写多个 flag + {@code long_task_reason} + {@code remark})。
|
*
|
* <h3>为什么要有这个"宽"接口</h3>
|
* 出院随访编排层({@code InhospTaskOrchestrator} 的 3 个 {@code *ForPatient})在写失败标志位时,
|
* 原实现有三种不同写法,写进去的列集合也不同:
|
* <ul>
|
* <li>有的在<b>按 inhospid 重读出来的对象</b>上改一个 flag,并把另两个 flag
|
* 从重读对象<b>原样带回</b>(因为 {@code updatePatMedInhosp} 是"传什么更新什么")
|
* —— 实际写了 3 个 flag;</li>
|
* <li>有的在<b>新鲜对象</b>上只 set 一个 flag —— 实际只写 1 个 flag。</li>
|
* </ul>
|
* 窄接口 {@link #updatePublicityFlag} 表达不了"一次写多个 flag",
|
* 所以加这个通道。调用方按原逻辑决定给哪些字段赋值,<b>null = 不改</b>
|
* (对应原 XML 每个字段各自的 {@code <if test="xxx != null">})。
|
*
|
* @param update 更新草稿({@code inhospid} 必填)
|
* @return true = 影响行数 > 0
|
*/
|
boolean updateVisitInhosp(com.ruoyi.common.core.service.dto.VisitInhospUpdateDto update);
|
|
/**
|
* 按离院科室/病区查「任务执行规则」(原 {@code ServiceTaskRuleMapper#selectServiceTaskRuleByDeptOrWard})。
|
*
|
* <h3>为什么放在这个端口上</h3>
|
* 该查询服务的是<b>出院随访</b>的规则编排({@code addSubTaskByRule}),
|
* 语义上不属于"宣教"。但本端口已经是"随访侧访问 smartor 只读配置"的统一入口
|
* (它已经提供 {@code findInHospForPublicity} / {@code findDeptPublicityTaskIds} 等),
|
* 再为一张单表加第四个端口不划算。这里在注释里写明用途,避免后人误以为它只服务宣教。
|
* <p>
|
* 迁移对应 {@code PatMedInhospServiceImpl#addSubTaskByRule} L1704-1707:
|
* <pre>
|
* ServiceTaskRule ruleQuery = new ServiceTaskRule();
|
* ruleQuery.setDeptcode(patMedInhosp1.getLeaveldeptcode());
|
* ruleQuery.setWardcode(patMedInhosp1.getLeavehospitaldistrictcode());
|
* ServiceTaskRule rule = serviceTaskRuleMapper.selectServiceTaskRuleByDeptOrWard(ruleQuery);
|
* </pre>
|
* 注意:<b>该查询最多返回一条</b>(原实现直接取单个对象)。
|
*
|
* @param leaveldeptcode 离院科室编码
|
* @param leavehospitaldistrictcode 离院病区编码
|
* @return 规则;未配置返回 {@code null}
|
*/
|
com.ruoyi.common.core.service.dto.VisitTaskRuleDto findTaskRule(String leaveldeptcode,
|
String leavehospitaldistrictcode);
|
}
|