package com.ruoyi.inhospvisit.service;
|
|
import com.ruoyi.common.core.service.PublicityDataPort;
|
import com.ruoyi.common.core.service.VisitTaskCreateApi;
|
import com.ruoyi.common.core.service.dto.VisitInhospUpdateDto;
|
import com.ruoyi.common.core.service.dto.VisitPendingSubtaskDto;
|
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.domain.row.VisitTaskdeptRow;
|
import com.ruoyi.inhospvisit.domain.row.VisitTaskdiagRow;
|
import com.ruoyi.inhospvisit.mapper.VisitArchiveMapper;
|
import com.ruoyi.inhospvisit.mapper.VisitInhospMapper;
|
import com.ruoyi.inhospvisit.mapper.VisitTaskdeptMapper;
|
import com.ruoyi.inhospvisit.mapper.VisitTaskdiagMapper;
|
import com.ruoyi.inhospvisit.support.InhospFlagWriter;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.collections4.CollectionUtils;
|
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 出院随访「编排器」—— 逐行搬自 {@code PatMedInhospServiceImpl}
|
* 的编排层({@code addSubTaskByRule} + 3 个 {@code *ForPatient} + {@code dealInHospInfo})。
|
*
|
* <h3>来源对照(@ b25c3b51)</h3>
|
* <table border="1">
|
* <tr><th>本类方法</th><th>原实现</th><th>行数</th></tr>
|
* <tr><td>{@link #addSubTaskByRule}</td><td>{@code addSubTaskByRule} L1691-1847</td><td>157</td></tr>
|
* <tr><td>{@link #addDeptSubTaskForPatient}</td><td>L1854-1887</td><td>34</td></tr>
|
* <tr><td>{@link #addWardSubTaskForPatient}</td><td>L1894-1935</td><td>42</td></tr>
|
* <tr><td>{@link #addIcd10SubTaskForPatient}</td><td>L1942-2001</td><td>60</td></tr>
|
* <tr><td>{@link #dealInHospInfo}</td><td>L1321-1359</td><td>39</td></tr>
|
* </table>
|
*
|
* <h3>⚠️ 三个 {@code *ForPatient} 的失败回写<b>写进去的列集合不同</b>,已逐一保真</h3>
|
* <table border="1">
|
* <tr><th>位置</th><th>原写法</th><th>实际写入的列</th></tr>
|
* <tr><td>科室·无模板(L1866-1872)</td>
|
* <td>重读对象 {@code setDeptcheckFlag("2")},另两个 flag 由重读对象原样带回</td>
|
* <td>deptcheck + wardcheck + diagcheck + reason</td></tr>
|
* <tr><td>科室·catch(L1879-1885)</td>
|
* <td>在<b>新鲜对象</b>上 set</td>
|
* <td>deptcheck + reason</td></tr>
|
* <tr><td>病区·失败(L1914-1920)</td>
|
* <td>重读对象 {@code setWardcheckFlag("2")},另两个 flag 原样带回</td>
|
* <td>wardcheck + deptcheck + diagcheck + reason</td></tr>
|
* <tr><td>病区·catch(L1927-1933)</td>
|
* <td>在新鲜对象上 set</td>
|
* <td>wardcheck + reason</td></tr>
|
* <tr><td>疾病·两处(L1967-1971 / L1985-1991)</td>
|
* <td>重读对象 {@code setDiagcheckFlag("2")} 并覆写 reason</td>
|
* <td>diagcheck + reason(注意:<b>没有</b>带回其它两个 flag)</td></tr>
|
* <tr><td>疾病·catch(L1993-1998)</td>
|
* <td>在新鲜对象上 set</td>
|
* <td>diagcheck + reason</td></tr>
|
* </table>
|
* 因此本类用 {@link PublicityDataPort#updateVisitInhosp(VisitInhospUpdateDto)}(可一次写多个 flag),
|
* 而不是窄的"单 flag"接口 —— 后者表达不了这些差异。
|
*
|
* <h3>⚠️ 站点差异(原样保留)</h3>
|
* <ul>
|
* <li>{@code nhfy}:疾病维度改用<b>主诊断名称</b> {@code leavediagname} 查询,而不是 ICD10 编码
|
* (因为南华附一的 icd10code 有重复);</li>
|
* <li>{@code xh}:{@code addSubTaskByRule} 里<b>整块跳过</b>病区 + 疾病两个维度(多处 {@code !xh} 判断)。</li>
|
* </ul>
|
*/
|
@Slf4j
|
@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}")
|
private String active;
|
|
@Autowired
|
private VisitInhospMapper inhospMapper;
|
|
@Autowired
|
private VisitArchiveMapper archiveMapper;
|
|
@Autowired
|
private VisitTaskdeptMapper taskdeptMapper;
|
|
@Autowired
|
private VisitTaskdiagMapper taskdiagMapper;
|
|
@Autowired
|
private InhospSubtaskWriter subtaskWriter;
|
|
@Autowired
|
private InhospFlagWriter flagWriter;
|
|
@Autowired
|
private ObjectProvider<PublicityDataPort> dataPortProvider;
|
|
@Autowired
|
private ObjectProvider<VisitTaskCreateApi> taskCreateApiProvider;
|
|
// ==========================================================================
|
// 1. 基于规则的任务生成(原 L1691-1847)
|
// ==========================================================================
|
|
/**
|
* 按 {@code service_task_rule} 的「首要(1)/次要(2)」规则编排科室/病区/疾病三个维度。
|
* <p>
|
* 逐行对应原 {@code addSubTaskByRule(String config, List<PatMedInhosp> patMedInhosps)}。
|
* <p>
|
* ⚠️ 规则查询 {@code serviceTaskRuleMapper.selectServiceTaskRuleByDeptOrWard} 仍在 smartor,
|
* 所以本方法接收<b>已查好的规则</b>(由调用方 {@code InhospVisitTaskService} 通过
|
* {@code PublicityDataPort} 取——该端口已含"按科室/病区查规则"的能力,见下)。
|
* 这样做是为了避免为"规则表"再加一个 Mapper 或端口。
|
*
|
* @param inhosp 待处理的出院患者
|
* @param archive 患者档案
|
* @param rule 已查好的规则;{@code null} = 未配置规则(全部生成)
|
* @param config {@code sys_config: visit.early.day}
|
*/
|
public void addSubTaskByRule(VisitInhospRow inhosp, VisitArchiveRow archive,
|
VisitTaskRule rule, String config) {
|
try {
|
if (rule == null) {
|
// 原 L1709-1716:规则为空,全部生成
|
log.info("【基于规则】患者{}未配置规则,执行全部生成逻辑", inhosp.getInhospid());
|
addDeptSubTaskForPatient(inhosp, archive, config);
|
if (!SITE_XH.equals(active)) {
|
addWardSubTaskForPatient(inhosp, archive, config);
|
addIcd10SubTaskForPatient(inhosp, archive, config);
|
}
|
return;
|
}
|
// 原 L1717-1726:有规则,按规则执行
|
log.info("【基于规则】患者{}查询到规则:deptRule={}, wradRule={}, diagRule={}",
|
inhosp.getInhospid(), rule.getDeptRule(), rule.getWradRule(), rule.getDiagRule());
|
|
boolean deptIsPrimary = "1".equals(rule.getDeptRule());
|
boolean wardIsPrimary = "1".equals(rule.getWradRule());
|
boolean diagIsPrimary = "1".equals(rule.getDiagRule());
|
boolean deptIsSecondary = "2".equals(rule.getDeptRule());
|
boolean wardIsSecondary = "2".equals(rule.getWradRule());
|
boolean diagIsSecondary = "2".equals(rule.getDiagRule());
|
|
boolean hasPrimaryRule = deptIsPrimary || wardIsPrimary || diagIsPrimary;
|
|
if (!hasPrimaryRule) {
|
// 原 L1829-1837:没有首要规则,全部生成
|
log.info("【基于规则】无首要规则,执行全部生成逻辑");
|
addDeptSubTaskForPatient(inhosp, archive, config);
|
if (!SITE_XH.equals(active)) {
|
addWardSubTaskForPatient(inhosp, archive, config);
|
addIcd10SubTaskForPatient(inhosp, archive, config);
|
}
|
return;
|
}
|
|
// 原 L1730-1754:先执行所有规则=1 的方法
|
int deptGenCount = 0;
|
int wardGenCount = 0;
|
int diagGenCount = 0;
|
|
if (deptIsPrimary) {
|
log.info("【基于规则】执行科室首要规则");
|
deptGenCount = addDeptSubTaskForPatient(inhosp, archive, config);
|
}
|
if (!SITE_XH.equals(active)) {
|
if (wardIsPrimary) {
|
log.info("【基于规则】执行病区首要规则");
|
wardGenCount = addWardSubTaskForPatient(inhosp, archive, config);
|
}
|
if (diagIsPrimary) {
|
log.info("【基于规则】执行疾病首要规则");
|
diagGenCount = addIcd10SubTaskForPatient(inhosp, archive, config);
|
}
|
}
|
|
int primaryGeneratedCount = deptGenCount + wardGenCount + diagGenCount;
|
log.info("【基于规则】首要规则执行结果: deptGen={}, wardGen={}, diagGen={}, total={}",
|
deptGenCount, wardGenCount, diagGenCount, primaryGeneratedCount);
|
|
String remark = inhosp.getRemark();
|
|
if (primaryGeneratedCount > 0) {
|
// 原 L1758-1796:至少一个首要规则成功
|
log.info("【基于规则】首要规则有成功(count={}),将次要规则对应flag设为2", primaryGeneratedCount);
|
if (deptIsSecondary) {
|
updateCheckFlag(inhosp, 1, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";首要规则已生成,次要规则跳过" : "首要规则已生成,次要规则跳过");
|
}
|
if (!SITE_XH.equals(active)) {
|
if (wardIsSecondary) {
|
updateCheckFlag(inhosp, 2, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";首要规则已生成,次要规则跳过" : "首要规则已生成,次要规则跳过");
|
}
|
if (diagIsSecondary) {
|
updateCheckFlag(inhosp, 3, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";首要规则已生成,次要规则跳过" : "首要规则已生成,次要规则跳过");
|
}
|
}
|
if (deptIsPrimary && deptGenCount > 0) {
|
updateCheckFlag(inhosp, 1, "1", StringUtils.isNotEmpty(remark)
|
? remark + ";科室首要规则生成成功" : "科室首要规则生成成功");
|
}
|
if (!SITE_XH.equals(active)) {
|
if (wardIsPrimary && wardGenCount > 0) {
|
updateCheckFlag(inhosp, 2, "1", StringUtils.isNotEmpty(remark)
|
? remark + ";病区首要规则生成成功" : "病区首要规则生成成功");
|
}
|
if (diagIsPrimary && diagGenCount > 0) {
|
updateCheckFlag(inhosp, 3, "1", StringUtils.isNotEmpty(remark)
|
? remark + ";疾病首要规则生成成功" : "疾病首要规则生成成功");
|
}
|
}
|
if (deptIsPrimary && deptGenCount == 0) {
|
updateCheckFlag(inhosp, 1, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";科室首要规则生成失败" : "科室首要规则生成失败");
|
}
|
if (!SITE_XH.equals(active)) {
|
if (wardIsPrimary && wardGenCount == 0) {
|
updateCheckFlag(inhosp, 2, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";病区首要规则生成失败" : "病区首要规则生成失败");
|
}
|
if (diagIsPrimary && diagGenCount == 0) {
|
updateCheckFlag(inhosp, 3, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";疾病首要规则生成失败" : "疾病首要规则生成失败");
|
}
|
}
|
} else {
|
// 原 L1797-1828:所有首要规则全部失败 → 把 =1 的置 2,然后执行次要规则
|
log.info("【基于规则】首要规则全部失败,将=1的flag设为2,开始执行次要规则");
|
if (deptIsPrimary) {
|
updateCheckFlag(inhosp, 1, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";科室首要规则全部失败" : "科室首要规则全部失败");
|
}
|
if (!SITE_XH.equals(active)) {
|
if (wardIsPrimary) {
|
updateCheckFlag(inhosp, 2, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";病区首要规则全部失败" : "病区首要规则全部失败");
|
}
|
if (diagIsPrimary) {
|
updateCheckFlag(inhosp, 3, "2", StringUtils.isNotEmpty(remark)
|
? remark + ";疾病首要规则全部失败" : "疾病首要规则全部失败");
|
}
|
}
|
if (deptIsSecondary) {
|
log.info("【基于规则】执行科室次要规则");
|
addDeptSubTaskForPatient(inhosp, archive, config);
|
}
|
if (!SITE_XH.equals(active)) {
|
if (wardIsSecondary) {
|
log.info("【基于规则】执行病区次要规则");
|
addWardSubTaskForPatient(inhosp, archive, config);
|
}
|
if (diagIsSecondary) {
|
log.info("【基于规则】执行疾病次要规则");
|
addIcd10SubTaskForPatient(inhosp, archive, config);
|
}
|
}
|
}
|
} catch (Exception e) {
|
// 原 L1839-1845
|
e.printStackTrace();
|
log.error("【基于规则】患者{}处理异常:{}", inhosp.getInhospid(), e.getMessage());
|
updateCheckFlag(inhosp, 1, "2", "基于规则处理异常");
|
}
|
}
|
|
/**
|
* 统一回写标志位 —— 委托 {@link InhospFlagWriter}(原 {@code updateCheckFlag})。
|
*/
|
private void updateCheckFlag(VisitInhospRow inhosp, Integer type, String flagValue, String remark) {
|
flagWriter.updateCheckFlag(inhosp, type, flagValue, remark);
|
}
|
|
// ==========================================================================
|
// 2. 科室维度(原 L1854-1887)
|
// ==========================================================================
|
|
/**
|
* 为单个患者生成科室维度的子任务。
|
*
|
* @return 生成的子任务数量
|
*/
|
public int addDeptSubTaskForPatient(VisitInhospRow inhosp, VisitArchiveRow archive, String config) {
|
int generatedCount = 0;
|
try {
|
// 原 L1857-1864:按患者所在科室查该科室的长期任务(dept_type=1 + service_type=2)
|
VisitTaskdeptRow query = new VisitTaskdeptRow();
|
query.setLongtask(1L);
|
query.setDeptCode(inhosp.getLeaveldeptcode());
|
query.setDeptType(DEPT_TYPE_DEPT);
|
query.setServiceType(SERVICE_TYPE_DISCHARGE);
|
query.setOrgid(inhosp.getOrgid());
|
List<VisitTaskdeptRow> taskdepts = taskdeptMapper.selectList(query);
|
|
if (CollectionUtils.isEmpty(taskdepts)) {
|
// 原 L1866-1872:⚠️ 在【重读对象】上改 deptcheck,并把另两个 flag 原样带回
|
VisitInhospRow fresh = inhospMapper.selectByInhospid(inhosp.getInhospid());
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setDeptcheckFlag("2");
|
u.setWardcheckFlag(fresh == null ? null : fresh.getWardcheckFlag());
|
u.setDiagcheckFlag(fresh == null ? null : fresh.getDiagcheckFlag());
|
// 原实现不判 null(fresh.getLongTaskReason() + "..."),原样保留
|
u.setLongTaskReason((fresh == null ? null : fresh.getLongTaskReason())
|
+ "该患者所在科室未配置离院长期任务;");
|
updateInhosp(u);
|
} else {
|
for (VisitTaskdeptRow t : taskdepts) {
|
subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 1, config);
|
generatedCount++;
|
}
|
}
|
} catch (Exception e) {
|
// 原 L1879-1885:⚠️ 在【新鲜对象】上 set —— 只写 deptcheck + reason
|
e.printStackTrace();
|
log.error("【科室任务】患者{}处理异常:{}", inhosp.getInhospid(), e.getMessage());
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setDeptcheckFlag("2");
|
u.setLongTaskReason("科室任务处理异常");
|
updateInhosp(u);
|
}
|
return generatedCount;
|
}
|
|
// ==========================================================================
|
// 3. 病区维度(原 L1894-1935)
|
// ==========================================================================
|
|
/**
|
* 为单个患者生成病区维度的子任务。
|
*
|
* @return 生成的子任务数量
|
*/
|
public int addWardSubTaskForPatient(VisitInhospRow inhosp, VisitArchiveRow archive, String config) {
|
int generatedCount = 0;
|
try {
|
String errorreason = null;
|
List<VisitTaskdeptRow> taskdeptList = null;
|
// 原 L1899-1912
|
if (!StringUtils.isEmpty(inhosp.getLeavehospitaldistrictcode())) {
|
VisitTaskdeptRow query = new VisitTaskdeptRow();
|
query.setLongtask(1L);
|
query.setDeptCode(inhosp.getLeavehospitaldistrictcode());
|
query.setDeptType(DEPT_TYPE_WARD);
|
query.setServiceType(SERVICE_TYPE_DISCHARGE);
|
query.setOrgid(inhosp.getOrgid());
|
taskdeptList = taskdeptMapper.selectList(query);
|
if (CollectionUtils.isEmpty(taskdeptList)) {
|
errorreason = "该患者所在病区未配置长期任务;";
|
}
|
} else {
|
errorreason = "离院病区为空;";
|
}
|
|
if (StringUtils.isNotEmpty(errorreason)) {
|
// 原 L1914-1920:⚠️ 重读对象 setWardcheck,另两个 flag 原样带回
|
VisitInhospRow fresh = inhospMapper.selectByInhospid(inhosp.getInhospid());
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setWardcheckFlag("2");
|
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);
|
updateInhosp(u);
|
} else {
|
for (VisitTaskdeptRow t : taskdeptList) {
|
subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 2, config);
|
generatedCount++;
|
}
|
}
|
} catch (Exception e) {
|
// 原 L1927-1933:新鲜对象 —— 只写 wardcheck + reason
|
e.printStackTrace();
|
log.error("【病区任务】患者{}处理异常:{}", inhosp.getInhospid(), e.getMessage());
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setWardcheckFlag("2");
|
u.setLongTaskReason("病区任务处理异常");
|
updateInhosp(u);
|
}
|
return generatedCount;
|
}
|
|
// ==========================================================================
|
// 4. 疾病维度(原 L1942-2001)
|
// ==========================================================================
|
|
/**
|
* 为单个患者生成疾病维度的子任务。
|
*
|
* @return 生成的子任务数量
|
*/
|
public int addIcd10SubTaskForPatient(VisitInhospRow inhosp, VisitArchiveRow archive, String config) {
|
int generatedCount = 0;
|
try {
|
// 原 L1945-1947
|
if (StringUtils.isEmpty(inhosp.getLeaveicd10code())) {
|
return 0;
|
}
|
|
// 原 L1949-1963:站点差异 —— nhfy 用诊断名,其它用 ICD10 编码
|
VisitTaskdiagRow query = new VisitTaskdiagRow();
|
query.setLongtask(1L);
|
if (SITE_NHFY.equals(active)) {
|
query.setIcd10name(inhosp.getLeavediagname());
|
if (StringUtils.isEmpty(inhosp.getLeavediagname())) {
|
// 原 L1954-1959:⚠️ 新鲜对象 —— 只写 diagcheck + reason(覆盖式)
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setDiagcheckFlag("2");
|
u.setLongTaskReason("该患者主诊断名称为空;");
|
updateInhosp(u);
|
return 0;
|
}
|
} else {
|
query.setIcd10code(inhosp.getLeaveicd10code());
|
}
|
query.setOrgid(inhosp.getOrgid());
|
List<VisitTaskdiagRow> taskdiags = taskdiagMapper.selectListByIcdName(query);
|
|
if (CollectionUtils.isEmpty(taskdiags)) {
|
// 原 L1967-1971:⚠️ 重读对象,但【只】setDiagcheckFlag + 覆写 reason
|
// (与科室/病区那两处不同:这里不带回其它 flag)
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setDiagcheckFlag("2");
|
u.setLongTaskReason("该患者所患疾病未配置长期任务;");
|
updateInhosp(u);
|
} else {
|
int flag = 0;
|
for (VisitTaskdiagRow t : taskdiags) {
|
// 原 L1975-1983:必须科室或病区能匹配上才建
|
if (StringUtils.isNotEmpty(t.getDeptCode())
|
&& t.getDeptCode().equals(inhosp.getLeaveldeptcode())) {
|
subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 3, config);
|
generatedCount++;
|
flag = 1;
|
} else if (StringUtils.isNotEmpty(t.getWardCode())
|
&& t.getWardCode().equals(inhosp.getLeavehospitaldistrictcode())) {
|
subtaskWriter.writeInSubTask(t.getTaskId(), true, inhosp, archive, 3, config);
|
generatedCount++;
|
flag = 1;
|
}
|
}
|
if (flag == 0) {
|
// 原 L1985-1991
|
log.error("该科室或病区对于患者所患疾病未配置长期任务,患者:{}", inhosp.getInhospid());
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setDiagcheckFlag("2");
|
u.setLongTaskReason("该科室或病区对于患者所患疾病未配置长期任务;");
|
updateInhosp(u);
|
}
|
}
|
} catch (Exception e) {
|
// 原 L1993-1998:新鲜对象 —— 只写 diagcheck + reason
|
e.printStackTrace();
|
log.error("【疾病任务】患者{}处理异常:{}", inhosp.getInhospid(), e.getMessage());
|
VisitInhospUpdateDto u = new VisitInhospUpdateDto();
|
u.setInhospid(inhosp.getInhospid());
|
u.setDiagcheckFlag("2");
|
u.setLongTaskReason("疾病任务处理异常");
|
updateInhosp(u);
|
}
|
return generatedCount;
|
}
|
|
// ==========================================================================
|
// 5. 再入院处理(原 L1321-1359)
|
// ==========================================================================
|
|
/**
|
* 再入院处理:新入院记录出现时,把该患者<b>旧的待执行随访</b>停掉。
|
* <p>
|
* 逐行对应原 {@code dealInHospInfo(List<PatMedInhosp> patMedInhospList)}。
|
* <p>
|
* ⚠️ 原实现的两个要点:
|
* <ol>
|
* <li>查询条件是 {@code patid + sendstate=2},<b>不设 taskid</b>(按患者全量查);
|
* 这里传 {@code null} 表示不按 taskid 过滤;</li>
|
* <li>景宁({@code 47255004333112711A1001})跳过停机 —— 不过这次判的是
|
* <b>{@code serviceSubtask1.getOrgid()}</b>(子任务的 orgid),不是入参患者的 orgid。</li>
|
* </ol>
|
*
|
* @param newInHosp 新入院的出入院记录(用它和旧子任务的 endtime 做比较)
|
*/
|
public void dealInHospInfo(VisitInhospRow newInHosp) {
|
try {
|
VisitTaskCreateApi api = taskApi();
|
if (api == null) {
|
log.warn("【出入院随访】VisitTaskCreateApi 不可用,跳过再入院处理。inhospid={}",
|
newInHosp.getInhospid());
|
return;
|
}
|
// 原 L1324-1328:patid + sendstate=2(不设 taskid)
|
List<VisitPendingSubtaskDto> pendingList =
|
api.findPendingSubtasks(newInHosp.getPatid(), null);
|
if (CollectionUtils.isEmpty(pendingList)) {
|
return;
|
}
|
for (VisitPendingSubtaskDto pending : pendingList) {
|
// 原 L1332-1335:不是长期任务,不处理
|
if (pending.getLongSendTime() == null) {
|
continue;
|
}
|
// 原 L1336-1340:⚠️ 判的是【子任务的 orgid】
|
boolean firstVisit = ORG_JINGNING.equals(pending.getOrgid());
|
if (firstVisit) {
|
continue;
|
}
|
// 原 L1342-1350:旧子任务的出院时间在新入院时间之前 → 停掉
|
if (pending.getEndtime() != null && newInHosp.getStarttime() != null
|
&& pending.getEndtime().before(newInHosp.getStarttime())) {
|
pending.setSendstate(4L);
|
pending.setIsVisitAgain(2);
|
pending.setRemark("患者再入院");
|
pending.setResult("error");
|
api.updatePendingSubtask(pending);
|
}
|
}
|
} catch (Exception e) {
|
// 原 L1355-1357
|
log.error("入院数据信息出异常了:{},{}", newInHosp, e.getMessage());
|
}
|
}
|
|
/** 景宁机构ID(原 L1338;与 InhospSubtaskWriter 里那份是同一常量,已逐字核对) */
|
private static final String ORG_JINGNING = "47255004333112711A1001";
|
|
// ==========================================================================
|
// 辅助
|
// ==========================================================================
|
|
private void updateInhosp(VisitInhospUpdateDto u) {
|
PublicityDataPort port = dataPort();
|
if (port == null) {
|
log.warn("【出入院随访】PublicityDataPort 不可用,无法写回标志位。inhospid={}", u.getInhospid());
|
return;
|
}
|
port.updateVisitInhosp(u);
|
}
|
|
private PublicityDataPort dataPort() {
|
if (dataPortProvider == null) {
|
return null;
|
}
|
try {
|
return dataPortProvider.stream().findFirst().orElse(null);
|
} catch (Exception e) {
|
log.warn("【出入院随访】获取 PublicityDataPort 失败:{}", e.toString());
|
return null;
|
}
|
}
|
|
private VisitTaskCreateApi taskApi() {
|
if (taskCreateApiProvider == null) {
|
return null;
|
}
|
try {
|
return taskCreateApiProvider.stream().findFirst().orElse(null);
|
} catch (Exception e) {
|
log.warn("【出入院随访】获取 VisitTaskCreateApi 失败:{}", e.toString());
|
return null;
|
}
|
}
|
|
/**
|
* {@code service_task_rule} 的规则快照(原 {@code ServiceTaskRule} 的随访侧视图)。
|
* <p>
|
* 规则查询本身仍由 {@code PublicityDataPort} 提供(它已经在服务宣教链路),
|
* 本类只消费结果,避免为规则表再加一个 Mapper。
|
*/
|
public static class VisitTaskRule {
|
|
/** 科室规则:"1"=首要 "2"=次要,其它=不参与 */
|
private String deptRule;
|
|
/** 病区规则(原字段名就是拼错的 {@code wradRule},保持同名以免读错) */
|
private String wradRule;
|
|
/** 疾病规则 */
|
private String diagRule;
|
|
public String getDeptRule() {
|
return deptRule;
|
}
|
|
public void setDeptRule(String deptRule) {
|
this.deptRule = deptRule;
|
}
|
|
public String getWradRule() {
|
return wradRule;
|
}
|
|
public void setWradRule(String wradRule) {
|
this.wradRule = wradRule;
|
}
|
|
public String getDiagRule() {
|
return diagRule;
|
}
|
|
public void setDiagRule(String diagRule) {
|
this.diagRule = diagRule;
|
}
|
}
|
|
/** 供测试/日志:本类是否拿到了必需的 Mapper */
|
boolean hasMappers() {
|
return inhospMapper != null && archiveMapper != null
|
&& taskdeptMapper != null && taskdiagMapper != null;
|
}
|
|
/** 预留:供日志使用的时间戳(避免 IDE 报未使用 import Date) */
|
@SuppressWarnings("unused")
|
private Date now() {
|
return new Date();
|
}
|
}
|