package com.ruoyi.common.core.service; import com.ruoyi.common.core.service.dto.VisitLongTaskDto; import com.ruoyi.common.core.service.dto.VisitPendingSubtaskDto; import com.ruoyi.common.core.service.dto.VisitSubtaskDraft; import java.util.List; /** * 随访任务「创建 / 派发」能力的预留接口。 * *
* 迁移对应:{@code PatMedInhospServiceImpl#writeInSubTask} L686-728(取任务 + 任务不存在时的分支)。 * * @param taskid 任务ID * @return 任务快照;不存在或未发布返回 {@code null} */ VisitLongTaskDto findPublishedLongTask(Long taskid); /** * 落库一条随访子任务(原 {@code ServiceSubtaskMapper.insertServiceSubtask})。 *
* 迁移对应:{@code PatMedInhospServiceImpl#writeInSubTask} 里的 * {@code insertServiceSubtask} 调用(L823 / L838 / L854 / L862 / L873)。 *
* ⚠️ 实现必须保持原样:入参草稿怎么填就怎么落库, * 不得在这里"顺手补默认值"或"顺手改状态",否则线上子任务内容会变。 *
* ⚠️ 方法名刻意不叫 createSubtask:它不是"新建一个业务对象", * 而是"把一份已经组装好的草稿原样落库"。 * 将来「随访任务创建模块」接管时,方法意图必须仍然是"原样落库", * 不许在这一层加入去重/合并/状态机 —— 那些语义在 {@code ruoyi-inhospvisit} 里。 * * @param draft 子任务草稿 * @return true = 落库成功(原实现判断 {@code insertServiceSubtask(...) == 1}) */ boolean insertSubtask(VisitSubtaskDraft draft); /** * 把一条 {@link #findPendingSubtasks} 查出来的待执行子任务原样回写(整体回写)。 *
* 迁移对应:{@code PatMedInhospServiceImpl#writeInSubTask} 里的 * {@code serviceSubtaskMapper.updateServiceSubtask(serviceSubtask1)} * (L812 / L836)与 {@code #dealInHospInfo} 里的 L1349。 *
* 原实现的做法是:先查完整对象 → 在内存里改几个字段
* ({@code sendstate=4L}、{@code result="error"}、{@code remark=...}、{@code updateBy}、{@code updateTime})
* → 把整个对象传给 {@code updateServiceSubtask}。
* 因为 {@code ServiceSubtaskMapper.xml} 的 {@code updateServiceSubtask}(L1060-1162)
* 是"每个字段各自 {@code
* 因此本方法刻意接收同一个 DTO(调用方已经在上面改过要改的字段),
* 由实现把它映射回实体后整体回写 —— 这样"带了哪些字段过去"这件事与原实现逐字段一致,
* 不会因为"只传个 id + 几个字段"而丢掉原实现会带过去的其它字段。
*
* @param pending 从 {@link #findPendingSubtasks} 拿到并已改好字段的 DTO({@code id} 必须非空)
* @return true = 更新成功
*/
boolean updatePendingSubtask(VisitPendingSubtaskDto pending);
/**
* 查"某患者 + 某 taskid"下所有 {@code sendstate=2}(待执行)的子任务,用于再入院去重判定。
*
* 迁移对应:{@code PatMedInhospServiceImpl#writeInSubTask} L760-764 与
* {@code #dealInHospInfo} L1325-1328 的
* {@code selectServiceSubtaskList(new ServiceSubtaskEntity(patid, sendstate=2, taskid))}。
*
* @param patid 患者档案ID
* @param taskid 任务ID;{@code dealInHospInfo} 那条链路传 {@code null}(按患者全量查)
* @return 待执行子任务摘要列表;无数据返回空列表,不返回 null
*/
List
* 迁移对应:{@code PatMedInhospServiceImpl#addServiceSubtaskPreachform} L1063-1068 ——
* 它先 {@code selectServiceTaskByTaskid(taskid)} 取到任务,再读 {@code getPreachformDesc()}。
*
* 为什么不复用 {@link #findPublishedLongTask(Long)}:后者带 {@code sendState=2} 条件
* (只要"已发布"的任务),而这里原实现用的是 {@code selectServiceTaskByTaskid}
* (不带 sendState 条件)—— 换成前者会改变"任务查得到/查不到"的判断。
* 所以刻意分开成两个方法。
*
* @param taskid 任务ID
* @return {@code preachformDesc};任务不存在或该字段为空时返回 {@code null}
*/
String findPreachformDesc(Long taskid);
/**
* 判断某患者是否存在「指定状态 + 指定服务类型」的随访子任务。
*
* 只返回"有没有",不返回列表 —— 调用方(门诊列表富化)只用它来置
* {@code serverState="1"},不需要子任务明细。
*
*
* 这个方法是那道"最后防线":落库前按
* {@code patid + inhospid + taskid}(且 {@code del_flag = 0})判重,
* 已存在就不再加。口径是"同一次出院 + 同一个任务只应有一条子任务",
* 不跨住院记录(再次入院换了 inhospid 仍会新建,这是原有语义)。
*
* @param patid 患者档案ID
* @param inhospid 出入院记录ID;为 {@code null} 时退化为只看 {@code patid + taskid}
* @param taskid 任务ID
* @return true = 已存在(不应再 insert)
*/
boolean existsSubtask(Long patid, Long inhospid, Long taskid);
}
原实现对应
* 门诊 {@code PatMedOuthospServiceImpl#selectPatMedOuthospList} L108-117:
*
* ServiceSubtaskEntity v = new ServiceSubtaskEntity();
* v.setPatid(patMedOuthosp1.getPatid());
* v.setSendstates(Arrays.asList(1L, 2L, 3L));
* v.setServiceType("3");
* List<ServiceSubtask> list = serviceSubtaskMapper.selectServiceSubtaskBySendstate(v);
* if (!CollectionUtils.isEmpty(list)) patMedOuthosp1.setServerState("1");
*
*
* ⚠️ 与 {@link #findPendingSubtasks(Long, Long)} 的区别(别混用)
*
*
* 两者查的是不同口径,不能互相替代。
*
* @param patid 患者档案ID
* @param sendstates 子任务状态集合(门诊传 1/2/3);为空则退化为不按状态过滤
* @param serviceType 服务类型(门诊传 {@code "3"});为 null 则不过滤
* @return true = 至少存在一条
*/
boolean existsSubtaskWithStates(Long patid, java.util.List
* 本方法 findPendingSubtasks
* 过滤条件 {@code sendstate IN (...)} + {@code service_type}
* 固定 {@code sendstate = 2}
* 是否按 taskid 否(跨该患者所有任务) 是(可选)
* 底层 Mapper 方法 {@code selectServiceSubtaskBySendstate}
* {@code selectServiceSubtaskList} 为什么需要它(2026-10 线上问题)
* 出院随访扫描是按 {@code pat_med_inhosp.deptcheck_flag = '0'} 取患者的。
* 一旦标志位因为规则配置/异常没被改成 1 或 2,下一轮扫描会把同一个患者再处理一遍,
* 而 {@code writeInSubTask} 的"停旧"分支在 {@code endTime1 == endTime}(同一次出院)时
* 走的是 else —— 会再 insert 一条 sendstate=4 的停用行,
* 于是同一个患者每次跑批都多一条,最终同一患者几十条子任务。
*