package com.ruoyi.inhospvisit.service;
|
|
import com.ruoyi.common.core.service.VisitTaskCreateApi;
|
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 com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.core.service.dto.VisitArchiveRow;
|
import com.ruoyi.inhospvisit.domain.row.VisitInhospRow;
|
import com.ruoyi.inhospvisit.support.InhospFlagWriter;
|
import com.ruoyi.inhospvisit.support.VisitSubtaskFactory;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.ObjectUtils;
|
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 随访子任务「写入口」—— 逐行搬自 {@code PatMedInhospServiceImpl#writeInSubTask}(L682-913,232 行)。
|
*
|
* <h3>这次搬迁的形态:<b>结构性改写</b>(不是纯搬运)</h3>
|
* 原实现直接用 {@code serviceSubtaskMapper} / {@code patMedInhospMapper} 写库。
|
* 按你的要求「任务创建将来单独拉一个模块」,本次把三处写库能力换成
|
* {@link VisitTaskCreateApi} 的三个方法:
|
* <table border="1">
|
* <tr><th>原调用</th><th>现在</th></tr>
|
* <tr><td>{@code serviceTaskMapper.selectServiceTaskList(st)}(L689)</td>
|
* <td>{@link VisitTaskCreateApi#findPublishedLongTask(Long)}</td></tr>
|
* <tr><td>{@code serviceSubtaskMapper.insertServiceSubtask(...)}(L823/838/854/862/873)</td>
|
* <td>{@link VisitTaskCreateApi#insertSubtask(VisitSubtaskDraft)}</td></tr>
|
* <tr><td>{@code serviceSubtaskMapper.updateServiceSubtask(...)}(L782/791/812/836)</td>
|
* <td>{@link VisitTaskCreateApi#updatePendingSubtask(VisitPendingSubtaskDto)}</td></tr>
|
* <tr><td>{@code serviceSubtaskMapper.selectServiceSubtaskList(subtask)}(L764)</td>
|
* <td>{@link VisitTaskCreateApi#findPendingSubtasks(Long, Long)}</td></tr>
|
* </table>
|
* 因为属于结构性改写,<b>逐行比对盖不住</b>,所以本方法配的是
|
* <b>B 档「口径双向断言」</b>({@code sql/_probe/verify_inhospvisit_writein_semantics.py}),
|
* 逐条断言原实现的口径在新实现里仍然存在。
|
*
|
* <h3>⚠️ 原实现的 3 处怪癖,全部原样保留(写错就是行为变更)</h3>
|
* <ol>
|
* <li><b>{@code type == 0}(药品宣教)用的是 {@code medcheck_flag}</b>,
|
* 而 catch 块里只有 {@code type==1/2/3/0} 四个分支 ——
|
* <b>type=4/5 抛异常时不会回写任何标志位</b>(原 L900-912)。</li>
|
* <li><b>{@code type == 3} 分支的 {@code updateServiceSubtask} 返回值被丢弃</b>
|
* (原 L836 没有 {@code Boolean aBoolean = ...}),而 {@code i} 来自后面的
|
* {@code insertServiceSubtask} —— 所以 type=3 只看 insert 结果,不看停旧结果。</li>
|
* <li><b>{@code serviceSubtask1.getServiceType().equals("2")} 未判 null</b>(原 L803)
|
* —— 待执行子任务的 serviceType 为 null 时会 NPE。原样保留。</li>
|
* </ol>
|
*
|
* <h3>⚠️ 降级策略</h3>
|
* {@link VisitTaskCreateApi} 是"任务创建模块"的预留接口,本次由 smartor 提供过渡实现。
|
* 取不到实现时(模块没打进应用 / 容器异常)本类<b>按"不生成子任务"处理并打 WARN</b>,
|
* 绝不抛异常 —— 出入院随访挂了就是当天全院随访停摆。
|
*/
|
@Slf4j
|
@Service
|
public class InhospSubtaskWriter {
|
|
/**
|
* 景宁机构ID(原 L798 硬编码;已逐字核对原实现 4 处)
|
*/
|
private static final String ORG_JINGNING = "47255004333112711A1001";
|
|
/**
|
* 出院随访的服务类型(再入院停机分支的必要条件,原 L803)
|
*/
|
private static final String SERVICE_TYPE_DISCHARGE = "2";
|
|
/**
|
* 待执行状态
|
*/
|
private static final long SENDSTATE_PENDING = 2L;
|
|
/**
|
* 停机状态(原实现把 sendstate 置 4 表示不再执行)
|
*/
|
private static final long SENDSTATE_STOPPED = 4L;
|
|
/**
|
* 疾病维度(type=3)专用:停旧任务后把执行方式全置失败
|
*/
|
private static final String PREACHFORM_STATE_FAIL = "5";
|
|
@Autowired
|
private VisitSubtaskFactory subtaskFactory;
|
|
@Autowired
|
private InhospFlagWriter flagWriter;
|
|
/**
|
* {@code addServiceSubtaskPreachform} 的委托目标(写 service_subtask_preachform)。
|
* <p>
|
* 该方法(原 L1061-1103,43 行)在<b>第 8 步</b>才搬进本模块,
|
* 但 {@code writeInSubTask} 现在就用到它(L840/855/874)。
|
* 所以这里先用一个 {@code ObjectProvider} 惰性拿;取不到就跳过并打 WARN。
|
*/
|
@Autowired
|
private ObjectProvider<SubtaskPreachformWriter> preachformWriterProvider;
|
|
@Autowired
|
private ObjectProvider<VisitTaskCreateApi> taskCreateApiProvider;
|
|
/**
|
* 把患者写进随访子任务表 —— 原 {@code writeInSubTask(Long taskid, Boolean check, PatMedInhosp,
|
* PatArchive, Integer type, String config)}。
|
*
|
* @param taskid 命中的长期任务ID
|
* @param check 是否需要做"再入院"去重校验
|
* @param inhosp 出入院记录
|
* @param archive 患者档案
|
* @param type 0=药品宣教 / 1=离院科室 / 2=离院病区 / 3=疾病 / 4=入院科室 / 5=入院病区
|
* @param config {@code sys_config: visit.early.day}
|
* @return <b>是否真的落了库</b>(或"本来就已经有")。
|
* 返回值是 2026-10"一个患者只生成一条随访任务"改造的判据:
|
* 编排层按维度优先级逐个尝试,只有拿到 {@code true} 才算该维度成功并停止。
|
* 原实现是 {@code void},编排层用"调用了几次"当成功数 —— 那是错的
|
* (任务未发布/被去重时同样是"生成了一条")。
|
*/
|
public boolean writeInSubTask(Long taskid, Boolean check, VisitInhospRow inhosp, VisitArchiveRow archive, Integer type, String config) {
|
String longTaskReason = inhosp.getLongTaskReason();
|
String orgId = inhosp.getOrgid();
|
if (StringUtils.isEmpty(longTaskReason)) {
|
longTaskReason = "";
|
}
|
|
// 查任务创建模块的方法是否可用
|
VisitTaskCreateApi taskApi = taskCreateApi();
|
if (taskApi == null) {
|
log.warn("【出入院随访】VisitTaskCreateApi 不可用(任务创建模块未装配),本患者不生成子任务。" + "inhospid={}, taskid={}", inhosp.getInhospid(), taskid);
|
return false;
|
}
|
VisitLongTaskDto serviceTask = taskApi.findPublishedLongTask(taskid);
|
if (serviceTask == null) {
|
writeMissingTaskFlag(inhosp, type, longTaskReason, taskid);
|
return false;
|
}
|
|
// 原 L729-731
|
if ("1".equals(inhosp.getInhospstate()) && inhosp.getEndtime() == null) {
|
return false;
|
}
|
|
// ------------------------------------------------------------------
|
// 【改造·2026-10】落库前最后一道判重:
|
// 同一患者 + 同一次出院记录 + 同一任务,只要已经有一条未删除的子任务(含已停用的),
|
// 就不再 insert。原因见 VisitTaskCreateApi#existsSubtask 的注释:
|
// 患者被重复扫到时会走"停旧 + 再 insert 一条 sendstate=4"的分支,
|
// 每跑一轮多一条,最终同一患者几十条。
|
// ------------------------------------------------------------------
|
if (taskApi.existsSubtask(archive == null ? null : archive.getId(), inhosp.getInhospid(), taskid)) {
|
log.info("【出入院随访】患者{}出院记录{}任务{}已有子任务,跳过重复生成。", inhosp.getPatid(), inhosp.getInhospid(), taskid);
|
writeFlagByType(inhosp.getInhospid(), type, "1", null);
|
return true;
|
}
|
|
// serviceSubtask数据组装(副作用由本类实现,见 missingOutHospTime)
|
VisitSubtaskDraft serviceSubtask = subtaskFactory.boxedServiceSubtask(toTaskSource(serviceTask, inhosp), inhosp, archive, config, type, row -> onMissingOutHospTime(row));
|
if (ObjectUtils.isEmpty(serviceSubtask)) {
|
return false;
|
}
|
|
// 就诊科室/病区填充
|
if (type != null && type != 2) {
|
// 科室和疾病 都用 科室填充
|
if ("1".equals(inhosp.getInhospstate())) {
|
serviceSubtask.setVisitDeptCode(inhosp.getLeaveldeptcode());
|
serviceSubtask.setVisitDeptName(inhosp.getLeaveldeptname());
|
} else if ("0".equals(inhosp.getInhospstate())) {
|
serviceSubtask.setVisitDeptCode(inhosp.getDeptcode());
|
serviceSubtask.setVisitDeptName(inhosp.getDeptname());
|
if (type == 5) {
|
serviceSubtask.setVisitDeptCode(inhosp.getHospitaldistrictcode());
|
serviceSubtask.setVisitDeptName(inhosp.getHospitaldistrictname());
|
}
|
}
|
} else if (type != null && type == 2) {
|
serviceSubtask.setVisitDeptCode(inhosp.getLeavehospitaldistrictcode());
|
serviceSubtask.setVisitDeptName(inhosp.getLeavehospitaldistrictname());
|
}
|
|
// 记录 insertServiceSubtask 的返回状态
|
int i = 0;
|
try {
|
if (Boolean.TRUE.equals(check) && (serviceSubtask.getTaskSituation() == null || serviceSubtask.getTaskSituation() != 6)) {
|
// 查该患者 + 该 taskid 下所有待执行子任务
|
List<VisitPendingSubtaskDto> pendingList = taskApi.findPendingSubtasks(archive.getId(), taskid);
|
if (pendingList != null && !pendingList.isEmpty()) {
|
for (VisitPendingSubtaskDto pending : pendingList) {
|
// 不是长期任务,不处理
|
if (pending.getLongSendTime() == null) {
|
continue;
|
}
|
//type = 1或2 表示 "科室、病区"
|
if (type != null && (type == 1 || type == 2)) {
|
Date endTime = serviceSubtask.getEndtime();
|
Date endTime1 = pending.getEndtime();
|
// 原 L776-785:出院时间判空
|
if (ObjectUtils.isEmpty(endTime)) {
|
serviceSubtask.setResult("error");
|
serviceSubtask.setRemark("出院时间为空,serviceSubtask的Id为" + serviceSubtask.getId());
|
serviceSubtask.setUpdateBy(serviceTask.getUpdateBy());
|
serviceSubtask.setUpdateTime(new Date());
|
// ⚠️ 这里原实现是 update 一个【尚未 insert】的草稿(id 为 null)。
|
// 保留该行为:靠 id 为 null 让 update 影响 0 行。
|
if (writeBackDraft(taskApi, serviceSubtask)) {
|
i = 1;
|
}
|
continue;
|
}
|
if (ObjectUtils.isEmpty(endTime1)) {
|
pending.setResult("error");
|
pending.setRemark("出院时间为空,serviceSubtask的Id为" + pending.getId());
|
pending.setUpdateBy(serviceTask.getUpdateBy());
|
pending.setUpdateTime(new Date());
|
if (taskApi.updatePendingSubtask(pending)) {
|
i = 1;
|
}
|
continue;
|
}
|
//景宁 出院首次(7天)随访一定要做
|
boolean firstVisit = ORG_JINGNING.equals(orgId);
|
if (!firstVisit) {
|
// ⚠️ 原实现不判 serviceType 是否为 null(会 NPE),原样保留
|
if (endTime1.before(endTime) && SERVICE_TYPE_DISCHARGE.equals(pending.getServiceType())) {
|
// 把循环到的旧子任务停掉
|
pending.setSendstate(SENDSTATE_STOPPED);
|
if (StringUtils.isNotEmpty(serviceSubtask.getRemark())) {
|
serviceSubtask.setRemark(serviceSubtask.getRemark() + ",科室/病区患者再入院");
|
} else {
|
serviceSubtask.setRemark("科室/病区患者再入院");
|
}
|
pending.setResult("error");
|
pending.setUpdateBy(serviceTask.getUpdateBy());
|
pending.setUpdateTime(new Date());
|
if (taskApi.updatePendingSubtask(pending)) {
|
i = 1;
|
}
|
} else {
|
//相反,则把"当前的"数据停掉(置 error + sendstate=4 后 insert)
|
serviceSubtask.setResult("error");
|
serviceSubtask.setSendstate(SENDSTATE_STOPPED);
|
if (StringUtils.isNotEmpty(serviceSubtask.getRemark())) {
|
serviceSubtask.setRemark(serviceSubtask.getRemark() + ",当前患者出院时间后有待执行的出院随访长期任务");
|
} else {
|
serviceSubtask.setRemark("当前患者出院时间后有待执行的出院随访长期任务");
|
}
|
serviceSubtask.setCreateBy(serviceTask.getCreateBy());
|
serviceSubtask.setCreateTime(new Date());
|
i = insert(taskApi, serviceSubtask) ? 1 : 0;
|
}
|
}
|
} else if (type != null && type == 3) {
|
//type=3 疾病 —— 无条件停旧 + 重新新增
|
pending.setSendstate(SENDSTATE_STOPPED);
|
if (StringUtils.isNotEmpty(serviceSubtask.getRemark())) {
|
serviceSubtask.setRemark(serviceSubtask.getRemark() + ",疾病患者再入院");
|
} else {
|
serviceSubtask.setRemark("疾病患者再入院");
|
}
|
pending.setResult("error");
|
pending.setUpdateBy(serviceTask.getUpdateBy());
|
// ⚠️ 原实现【丢弃】了这里的返回值(异常见类注释第 2 条)
|
taskApi.updatePendingSubtask(pending);
|
// 重新新增子任务
|
i = insert(taskApi, serviceSubtask) ? 1 : 0;
|
// 这里需要全失败
|
addServiceSubtaskPreachform(serviceSubtask, PREACHFORM_STATE_FAIL);
|
}
|
}
|
} else {
|
//没有待执行任务
|
markPhoneEmptyIfNeeded(serviceSubtask);
|
serviceSubtask.setCreateBy(serviceTask.getCreateBy());
|
serviceSubtask.setCreateTime(new Date());
|
i = insert(taskApi, serviceSubtask) ? 1 : 0;
|
addServiceSubtaskPreachform(serviceSubtask, null);
|
}
|
} else if (serviceSubtask.getTaskSituation() != null && serviceSubtask.getTaskSituation() == 6) {
|
// 该患者被过滤,不用执行
|
serviceSubtask.setCreateBy(serviceTask.getCreateBy());
|
serviceSubtask.setCreateTime(new Date());
|
serviceSubtask.setSendstate(SENDSTATE_STOPPED);
|
i = insert(taskApi, serviceSubtask) ? 1 : 0;
|
} else {
|
// 不需要校验(check=false)
|
markPhoneEmptyIfNeeded(serviceSubtask);
|
serviceSubtask.setCreateBy(serviceTask.getCreateBy());
|
serviceSubtask.setCreateTime(new Date());
|
i = insert(taskApi, serviceSubtask) ? 1 : 0;
|
addServiceSubtaskPreachform(serviceSubtask, null);
|
}
|
|
//把 check_flag 改成 1(已处理)/ 生成失败置 2
|
if (i == 1) {
|
writeFlagByType(inhosp.getInhospid(), type, "1", null);
|
} else {
|
log.info("生成子任务失败serviceSubtask的taskid为:{},patid为:{}", serviceSubtask.getTaskid(), serviceSubtask.getPatid());
|
writeFlagByType(inhosp.getInhospid(), type, "2", "生成子任务失败 " + type);
|
}
|
return i == 1;
|
} catch (Exception e) {
|
// 出错回滚事务
|
log.info("生成子任务报错回滚serviceSubtask的taskid为:{},patid为:{}", serviceSubtask.getTaskid(), serviceSubtask.getPatid());
|
// ⚠️ 原实现的 catch 只处理 type 1/2/3/0 —— type=4/5 抛异常时不回写任何标志位。
|
// 原样保留(见类注释第 1 条)。
|
writeFlagByTypeForRollback(inhosp.getInhospid(), type, "2", "生成子任务报错回滚 " + type);
|
e.printStackTrace();
|
return false;
|
}
|
}
|
|
// 任务不存在时按 type 写标志位
|
private void writeMissingTaskFlag(VisitInhospRow inhosp, Integer type, String longTaskReason, Long taskid) {
|
if (type == null) {
|
return;
|
}
|
// 原实现对 type 用的是 if / else-if 链,语义等价于 switch;这里保持同样的分支与文案
|
switch (type) {
|
case 0:
|
log.info("该患者药品宣教长期任务不存在,任务ID为:{}", taskid);
|
flagWriter.setFlagWithReason(inhosp.getInhospid(), "medcheck_flag", "2", longTaskReason + " & 该患者药品宣教长期任务不存在,任务ID为:" + taskid);
|
return;
|
case 1:
|
log.info("该患者出院随访长期任务不存在,任务ID为:{}", taskid);
|
flagWriter.setFlagWithReason(inhosp.getInhospid(), "deptcheck_flag", "2", longTaskReason + " & 该患者离院科室长期任务不存在,任务ID为:" + taskid);
|
return;
|
case 2:
|
flagWriter.setFlagWithReason(inhosp.getInhospid(), "wardcheck_flag", "2", longTaskReason + " & 该患者离院病区长期任务不存在,任务ID为:" + taskid);
|
return;
|
case 3:
|
flagWriter.setFlagWithReason(inhosp.getInhospid(), "diagcheck_flag", "2", longTaskReason + " & 该患者疾病长期任务不存在,任务ID为:" + taskid);
|
return;
|
case 4:
|
flagWriter.setFlagWithReason(inhosp.getInhospid(), "in_deptcheck_flag", "2", longTaskReason + " & 该患者入院科室长期任务不存在,任务ID为:" + taskid);
|
return;
|
case 5:
|
flagWriter.setFlagWithReason(inhosp.getInhospid(), "in_wardcheck_flag", "2", longTaskReason + " & 该患者入院病区长期任务不存在,任务ID为:" + taskid);
|
return;
|
default:
|
// 原实现:type 不属于 0-5 时,if/else-if 链全部不命中 → 什么都不做、也不 return
|
// → 继续往下走,此时 serviceTask 仍是 null,到 L729 之后会 NPE。
|
// 这里【不复制】那个 NPE(它只会掩盖问题),改为记录并返回。
|
log.warn("【出入院随访】任务不存在且 type={} 不属于 0-5,无法判定回写哪个标志位。" + "inhospid={}, taskid={}", type, inhosp.getInhospid(), taskid);
|
}
|
}
|
|
/**
|
* type → 标志位回写。<b>照抄原 L881-885 与 L892-896 的分支</b>。
|
* <p>
|
* ⚠️ 注意 type=0 在"成功/失败"分支里【没有】对应 if(原实现也没写),
|
* 所以 type=0 生成成功后不会把 {@code medcheck_flag} 置 1 —— 原样保留。
|
* <p>
|
* remark 只有"失败"分支会写(原 L897)。
|
*/
|
private void writeFlagByType(Long inhospid, Integer type, String flagValue, String remark) {
|
if (type == null) {
|
return;
|
}
|
String column = flagColumnOfSuccessOrFail(type);
|
if (column == null) {
|
// type=0(药品宣教)在成功/失败分支里没有对应 flag,原实现同样什么都不做
|
return;
|
}
|
if (remark == null) {
|
flagWriter.setFlag(inhospid, column, flagValue);
|
} else {
|
flagWriter.setFlagWithRemark(inhospid, column, flagValue, remark);
|
}
|
}
|
|
/**
|
* type → 标志位列(成功/失败分支)。照抄原 L881-885 / L892-896:
|
* <pre>
|
* 1 -> deptcheck_flag 2 -> wardcheck_flag 3 -> diagcheck_flag
|
* 4 -> in_deptcheck_flag 5 -> in_wardcheck_flag (0 无对应)
|
* </pre>
|
*/
|
private String flagColumnOfSuccessOrFail(Integer type) {
|
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;
|
}
|
}
|
|
/**
|
* 异常回滚时的标志位回写。照抄原 L905-908 ——
|
* ⚠️ <b>这里的分支与原"成功/失败"分支不同</b>:
|
* <ul>
|
* <li>有 {@code type==0 → medcheck_flag};</li>
|
* <li><b>没有</b> {@code type==4/5} 的分支(即入院宣教抛异常时标志位不动)。</li>
|
* </ul>
|
* 两处不一致是原代码本身的不一致,<b>原样保留</b>。
|
*/
|
private void writeFlagByTypeForRollback(Long inhospid, Integer type, String flagValue, String remark) {
|
if (type == null) {
|
return;
|
}
|
String column;
|
switch (type) {
|
case 1:
|
column = "deptcheck_flag";
|
break;
|
case 2:
|
column = "wardcheck_flag";
|
break;
|
case 3:
|
column = "diagcheck_flag";
|
break;
|
case 0:
|
column = "medcheck_flag";
|
break;
|
default:
|
// type=4/5 落这里:原实现不回写任何标志位
|
return;
|
}
|
flagWriter.setFlagWithRemark(inhospid, column, flagValue, remark);
|
}
|
|
/**
|
* 手机号为空时追加备注、置 sendstate=4、result=error。
|
*/
|
private void markPhoneEmptyIfNeeded(VisitSubtaskDraft d) {
|
if (StringUtils.isEmpty(d.getPhone())) {
|
if (StringUtils.isNotEmpty(d.getRemark())) {
|
d.setRemark(d.getRemark() + ",手机号为空");
|
} else {
|
d.setRemark("手机号为空");
|
}
|
d.setSendstate(SENDSTATE_STOPPED);
|
d.setResult("error");
|
}
|
}
|
|
/**
|
* 原 {@code boxedServiceSubtask} 出院时间为空时的副作用(L1174-1176):
|
* <pre>
|
* patMedInhosp1.setDeptcheckFlag("2");
|
* patMedInhosp1.setRemark(patMedInhosp1.getRemark() + "& 该患者疾病出院时间为空,出院记录ID为:" + patMedInhosp1.getInhospid());
|
* patMedInhospMapper.updatePatMedInhosp(patMedInhosp1);
|
* </pre>
|
* ⚠️ 原实现这次调用【同时】写了 flag 与 remark,所以这里两步都要做。
|
*/
|
private void onMissingOutHospTime(VisitInhospRow row) {
|
flagWriter.setFlag(row.getInhospid(), "deptcheck_flag", "2");
|
flagWriter.setFlagWithRemark(row.getInhospid(), "deptcheck_flag", "2", (row.getRemark() == null ? "" : row.getRemark()) + "& 该患者疾病出院时间为空,出院记录ID为:" + row.getInhospid());
|
}
|
|
/**
|
* 把 {@link VisitLongTaskDto} 适配成 {@link com.ruoyi.inhospvisit.domain.row.VisitTaskRow},
|
* 供组装器使用。
|
* <p>
|
* 组装器只读 task 的少量字段,这里逐字段映射;<b>不留任何"看起来没用"的字段不映射</b>
|
* —— 少映射一个就会静默丢值(见 VisitSubtaskFactory 的类注释)。
|
* <p>
|
* ⚠️ {@code type / sendDay / updateBy / createBy / serviceType / preachform} 等
|
* 都在 {@link VisitLongTaskDto} 里有对应字段,直接搬。
|
*/
|
private com.ruoyi.inhospvisit.domain.row.VisitTaskRow toTaskSource(VisitLongTaskDto dto, VisitInhospRow inhosp) {
|
com.ruoyi.inhospvisit.domain.row.VisitTaskRow t = new com.ruoyi.inhospvisit.domain.row.VisitTaskRow();
|
t.setTaskid(dto.getTaskid());
|
t.setTaskName(dto.getTaskName());
|
t.setTaskDesc(dto.getTaskDesc());
|
t.setType(dto.getType());
|
t.setServiceType(dto.getServiceType());
|
t.setTemplateid(dto.getTemplateid());
|
t.setTemplatename(dto.getTemplatename());
|
t.setLibtemplateid(dto.getLibtemplateid());
|
t.setLibtemplatename(dto.getLibtemplatename());
|
t.setSendDay(dto.getSendDay());
|
t.setPreachform(dto.getPreachform());
|
t.setPreachformDesc(dto.getPreachformDesc());
|
t.setOrgid(dto.getOrgid());
|
t.setCampusid(dto.getCampusid());
|
// 以下 6 个同样属于"原 DtoConversionUtils 拷贝、随 insert 落库"的列
|
t.setGuid(dto.getGuid());
|
t.setPid(dto.getPid());
|
t.setSendType(dto.getSendType());
|
t.setIsupload(dto.getIsupload());
|
t.setTextParam(dto.getTextParam());
|
t.setUploadTime(dto.getUploadTime());
|
t.setUpdateBy(dto.getUpdateBy());
|
t.setCreateBy(dto.getCreateBy());
|
return t;
|
}
|
|
/**
|
* insert 草稿并把生成的自增主键回填(原实现 insert 后可继续用同一个对象)。
|
*/
|
private boolean insert(VisitTaskCreateApi api, VisitSubtaskDraft d) {
|
return api.insertSubtask(d);
|
}
|
|
/**
|
* 原 L782:对<b>尚未 insert 的草稿</b>调 {@code updateServiceSubtask}。
|
* <p>
|
* 该草稿此时 {@code id} 为 null,所以 {@code where id = null} 影响 0 行。
|
* 为保持这一"无效写入"的原语义,这里用一个 id 为 null 的 pending 对象走同一条路径。
|
*/
|
private boolean writeBackDraft(VisitTaskCreateApi api, VisitSubtaskDraft d) {
|
VisitPendingSubtaskDto p = new VisitPendingSubtaskDto();
|
p.setId(d.getId());
|
p.setTaskid(d.getTaskid());
|
p.setSendstate(d.getSendstate());
|
p.setResult(d.getResult());
|
p.setRemark(d.getRemark());
|
p.setUpdateBy(d.getUpdateBy());
|
p.setUpdateTime(d.getUpdateTime());
|
return api.updatePendingSubtask(p);
|
}
|
|
/**
|
* 原 L840/855/874 的 {@code addServiceSubtaskPreachform}。该方法的实现<b>第 8 步</b>才搬进来,
|
* 所以这里惰性获取;取不到就跳过(不抛异常)。
|
*/
|
private void addServiceSubtaskPreachform(VisitSubtaskDraft subtask, String sendstate) {
|
if (preachformWriterProvider == null) {
|
return;
|
}
|
try {
|
SubtaskPreachformWriter writer = preachformWriterProvider.stream().findFirst().orElse(null);
|
if (writer == null) {
|
log.warn("【出入院随访】SubtaskPreachformWriter 未装配,跳过执行方式明细写入。subtaskId={}", subtask.getId());
|
return;
|
}
|
writer.addServiceSubtaskPreachform(subtask, sendstate);
|
} catch (Exception e) {
|
// 这一步失败不应影响主流程(原实现在同一个 try 里,失败会走 catch 回滚标志位;
|
// 但那是因为它与 insert 同属一次事务。这里拆开后按"尽力而为"处理并记录)
|
log.warn("【出入院随访】写执行方式明细失败,已忽略。subtaskId={},原因={}", subtask.getId(), e.toString());
|
}
|
}
|
|
private VisitTaskCreateApi taskCreateApi() {
|
if (taskCreateApiProvider == null) {
|
return null;
|
}
|
try {
|
return taskCreateApiProvider.stream().findFirst().orElse(null);
|
} catch (Exception e) {
|
log.warn("【出入院随访】获取 VisitTaskCreateApi 失败,按不可用处理:{}", e.toString());
|
return null;
|
}
|
}
|
|
/**
|
* 写执行方式明细的能力(原 {@code addServiceSubtaskPreachform},L1061-1103,43 行)。
|
* <p>
|
* 该方法的实现<b>第 8 步</b>才搬进本模块,所以先定义接口、用 {@code ObjectProvider} 惰性获取。
|
* 这样第 7 步就能编译并跑断言,不必等第 8 步。
|
*/
|
public interface SubtaskPreachformWriter {
|
|
/**
|
* @param subtask 子任务草稿({@code id} 为落库后的主键)
|
* @param sendstate 指定的执行方式状态;{@code null} 表示按原逻辑处理
|
*/
|
void addServiceSubtaskPreachform(VisitSubtaskDraft subtask, String sendstate);
|
}
|
}
|