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})。 * *
| 本类方法 | 原实现 | 行数 |
|---|---|---|
| {@link #addSubTaskByRule} | {@code addSubTaskByRule} L1691-1847 | 157 |
| {@link #addDeptSubTaskForPatient} | L1854-1887 | 34 |
| {@link #addWardSubTaskForPatient} | L1894-1935 | 42 |
| {@link #addIcd10SubTaskForPatient} | L1942-2001 | 60 |
| {@link #dealInHospInfo} | L1321-1359 | 39 |
| 位置 | 原写法 | 实际写入的列 |
|---|---|---|
| 科室·无模板(L1866-1872) | *重读对象 {@code setDeptcheckFlag("2")},另两个 flag 由重读对象原样带回 | *deptcheck + wardcheck + diagcheck + reason |
| 科室·catch(L1879-1885) | *在新鲜对象上 set | *deptcheck + reason |
| 病区·失败(L1914-1920) | *重读对象 {@code setWardcheckFlag("2")},另两个 flag 原样带回 | *wardcheck + deptcheck + diagcheck + reason |
| 病区·catch(L1927-1933) | *在新鲜对象上 set | *wardcheck + reason |
| 疾病·两处(L1967-1971 / L1985-1991) | *重读对象 {@code setDiagcheckFlag("2")} 并覆写 reason | *diagcheck + reason(注意:没有带回其它两个 flag) |
| 疾病·catch(L1993-1998) | *在新鲜对象上 set | *diagcheck + reason |
* 逐行对应原 {@code addSubTaskByRule(String config, List
* ⚠️ 规则查询 {@code serviceTaskRuleMapper.selectServiceTaskRuleByDeptOrWard} 仍在 smartor,
* 所以本方法接收已查好的规则(由调用方 {@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
* 逐行对应原 {@code dealInHospInfo(List
* ⚠️ 原实现的两个要点:
*
* 规则查询本身仍由 {@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();
}
}
*
*
* @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