package com.ruoyi.inhospvisit.api;
|
|
import com.ruoyi.inhospvisit.config.InhospVisitProperties;
|
import com.ruoyi.inhospvisit.config.InhospVisitSwitch;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
/**
|
* 出入院随访模块对外门面(<b>常驻 Bean</b>)。
|
* <p>
|
* 这是其它模块访问出入院随访能力的<b>唯一入口</b>。
|
*
|
* <h3>与内部实现的关系(照抄满意度模块,5 个坑全部规避)</h3>
|
* <ul>
|
* <li>实现类 {@link DefaultInhospVisitApi} <b>常驻</b>(不用 {@code @ConditionalOnProperty}
|
* —— 那个只在启动时求值一次,与"改完参数即时生效"冲突);</li>
|
* <li>开关在 {@code sys_config} 的 {@code inhospvisit.enabled},由
|
* {@link InhospVisitSwitch} <b>运行时</b>读取(10 秒进程内缓存),改完无需重启;</li>
|
* <li>本门面<b>永远</b>是 Spring Bean,因此调用方({@code RyTask} 定时任务、
|
* {@code PatMedInhospController})的 {@code @Autowired} 在任何开关状态下都<b>不会启动失败</b>;</li>
|
* <li>关闭时各方法返回安全空值并打 WARN,<b>不抛异常</b>,保证调用方主流程照常完成。</li>
|
* </ul>
|
*
|
* <h3>⚠️ 本门面同时实现三个接口</h3>
|
* <ul>
|
* <li>{@link InhospVisitApi} —— 本模块的<b>随访业务能力契约</b>(smartor / ruoyi-quartz 用),
|
* 受 {@code inhospvisit.enabled} 开关管辖;</li>
|
* <li>{@link InhospVisitDataService} —— <b>基础出入院信息读写契约</b>(本次新增)。
|
* {@code PatMedInhospMapper} 已独占搬入本模块,其它模块一律经此访问;
|
* <b>刻意不受开关管辖</b>,否则关闭随访会连带让 HIS 采集瘫痪;</li>
|
* <li>{@code com.ruoyi.common.core.service.PublicitySubtaskApi} —— <b>下沉给宣教模块的最小面</b>。
|
* 因为 ruoyi-publicity 不能依赖本模块(否则双向依赖),只能按 ruoyi-common 里的接口查找。</li>
|
* </ul>
|
*
|
* <h3>使用示例</h3>
|
* <pre>
|
* @Autowired
|
* private InhospVisitFacade inhospVisitFacade;
|
*
|
* if (inhospVisitFacade.isEnabled()) {
|
* inhospVisitFacade.dealOutHospInfo(config);
|
* }
|
*
|
* // 基础出入院信息:不需要判开关
|
* List<PatMedInhosp> rows = inhospVisitFacade.selectPatMedInhospList(query);
|
* </pre>
|
*/
|
@Slf4j
|
@Component
|
public class InhospVisitFacade implements InhospVisitApi,
|
InhospVisitDataService,
|
com.ruoyi.common.core.service.PreachformApi,
|
com.ruoyi.common.core.service.PublicitySubtaskApi {
|
|
private final InhospVisitProperties properties;
|
|
/**
|
* 宣教单({@code service_subtask_preachform})数据访问。
|
* <p>
|
* ⚠️ 用 {@code ObjectProvider} 惰性取,而不是直接注入接口 —— 理由同 {@code dataService}:
|
* 本类自身也实现了 {@code PreachformApi},按接口类型直接注入会命中"正在创建的自己"
|
* ({@code BeanCurrentlyInCreationException})。
|
* <p>
|
* 该表的归属模块是本模块;跨模块 SQL 收口后,外部只经 {@code PreachformApi} 访问它
|
* (此前 smartor 里另有一整份同表 Mapper 与 XML,已删除)。
|
*/
|
private final ObjectProvider<com.ruoyi.common.core.service.PreachformApi> preachformApiProvider;
|
|
/**
|
* 运行时开关({@code sys_config} 优先,{@link InhospVisitProperties} 兜底)
|
*/
|
private final InhospVisitSwitch inhospVisitSwitch;
|
|
/**
|
* 内部实现;模块关闭时为 {@code null}。
|
* <p>
|
* 用 {@code ObjectProvider} 惰性获取:即使实现 Bean 不存在也不会导致注入失败。
|
*/
|
private final ObjectProvider<InhospVisitApi> apiProvider;
|
|
/**
|
* 基础出入院信息数据访问(<b>必存在</b>,不受开关管辖)。
|
* <p>
|
* ⚠️ <b>用 {@link ObjectProvider} 惰性获取,并在解析时过滤掉"自己"</b>:
|
* 本类自身也实现了 {@link InhospVisitDataService},若直接注入接口类型,
|
* Spring 解析候选时会命中<b>正在创建的自己</b>,抛
|
* {@code BeanCurrentlyInCreationException}(实测确认)。
|
* 详见 {@link #firstDataServiceOrNull(ObjectProvider)}。
|
* <p>
|
* 用 {@code ObjectProvider} 而非直接注入还带来装配健壮性:容器里没有该实现
|
* (例如不起数据库的测试上下文)时,门面依然能装配,数据方法走降级分支,
|
* 而不会让整个应用启动失败。
|
*/
|
private final InhospVisitDataService dataService;
|
|
/**
|
* Spring 使用的构造器。
|
* <p>
|
* ⚠️ <b>必须显式标注 {@code @Autowired}</b>:本类有两个公开构造器
|
* (另一个是给测试/非 Spring 环境用的),若不标注,Spring 会因为"构造器不唯一"
|
* 而退回查找无参构造器,从而在启动时报 {@code No default constructor found}。
|
* —— 这是满意度模块<b>实机踩到</b>的缺陷,此处刻意保留同样的写法与注释。
|
*/
|
@Autowired
|
public InhospVisitFacade(InhospVisitProperties properties,
|
InhospVisitSwitch inhospVisitSwitch,
|
ObjectProvider<InhospVisitApi> apiProvider,
|
ObjectProvider<InhospVisitDataService> dataServiceProvider,
|
ObjectProvider<com.ruoyi.common.core.service.PreachformApi> preachformApiProvider) {
|
this.properties = properties;
|
this.inhospVisitSwitch = inhospVisitSwitch;
|
this.apiProvider = apiProvider;
|
this.dataService = firstDataServiceOrNull(dataServiceProvider);
|
this.preachformApiProvider = preachformApiProvider;
|
}
|
|
/**
|
* 取宣教单数据访问实现;容器里没有、状态异常、或<b>只找到自己</b>时返回 {@code null}。
|
* <p>
|
* ⚠️ 与 {@link #firstDataServiceOrNull} 同一手法与理由(自引用 / 循环依赖)。
|
*/
|
private com.ruoyi.common.core.service.PreachformApi preachformOrNull() {
|
if (preachformApiProvider == null) {
|
return null;
|
}
|
try {
|
return preachformApiProvider.stream()
|
.filter(svc -> svc != this)
|
.findFirst()
|
.orElse(null);
|
} catch (Exception e) {
|
log.warn("【出入院随访】获取宣教单数据服务失败,相关访问将降级:{}", e.toString());
|
return null;
|
}
|
}
|
|
/**
|
* 数据服务是否不可用(不可用时打 WARN 并返回 true)
|
*/
|
private boolean preachformUnavailable(String method) {
|
if (preachformOrNull() == null) {
|
log.warn("【出入院随访】宣教单数据服务不可用,{} 跳过。", method);
|
return true;
|
}
|
return false;
|
}
|
|
// ==================================================================
|
// 宣教单 service_subtask_preachform(PreachformApi)
|
//
|
// ⚠️ 与上面 6 个随访方法的关键区别:以下方法【不做开关判断】。
|
// 它是跨模块 SQL 收口后的数据访问入口(替代 smartor 里那份同表 Mapper),
|
// 属数据基础设施;开关只该控制"要不要生成随访"。
|
// ==================================================================
|
|
@Override
|
public com.ruoyi.common.core.service.dto.VisitPreachformRow findById(Long id) {
|
return preachformUnavailable("findById") ? null : preachformOrNull().findById(id);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.common.core.service.dto.VisitPreachformRow> findList(
|
com.ruoyi.common.core.service.dto.VisitPreachformRow query) {
|
return preachformUnavailable("findList")
|
? java.util.Collections.<com.ruoyi.common.core.service.dto.VisitPreachformRow>emptyList()
|
: preachformOrNull().findList(query);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.common.core.service.dto.VisitPreachformRow> findByTaskidAndOrgid(
|
Long taskid, String orgid) {
|
return preachformUnavailable("findByTaskidAndOrgid")
|
? java.util.Collections.<com.ruoyi.common.core.service.dto.VisitPreachformRow>emptyList()
|
: preachformOrNull().findByTaskidAndOrgid(taskid, orgid);
|
}
|
|
@Override
|
public boolean insert(com.ruoyi.common.core.service.dto.VisitPreachformRow row) {
|
return !preachformUnavailable("insert") && preachformOrNull().insert(row);
|
}
|
|
@Override
|
public boolean updateById(com.ruoyi.common.core.service.dto.VisitPreachformRow row) {
|
return !preachformUnavailable("updateById") && preachformOrNull().updateById(row);
|
}
|
|
@Override
|
public boolean updateByCondition(com.ruoyi.common.core.service.dto.VisitPreachformRow row) {
|
return !preachformUnavailable("updateByCondition") && preachformOrNull().updateByCondition(row);
|
}
|
|
@Override
|
public boolean softDeleteById(Long id) {
|
return !preachformUnavailable("softDeleteById") && preachformOrNull().softDeleteById(id);
|
}
|
|
@Override
|
public boolean softDeleteByIds(Long[] ids) {
|
return !preachformUnavailable("softDeleteByIds") && preachformOrNull().softDeleteByIds(ids);
|
}
|
|
@Override
|
public boolean softDeleteBySubid(Long subid) {
|
return !preachformUnavailable("softDeleteBySubid") && preachformOrNull().softDeleteBySubid(subid);
|
}
|
|
/**
|
* 取数据服务实现;容器里没有、状态异常、或<b>只找到自己</b>时返回 {@code null}。
|
* <p>
|
* ⚠️ <b>必须过滤掉"自己"</b>,两个理由:
|
* <ol>
|
* <li><b>自引用</b>:本类自身也实现了 {@link InhospVisitDataService}。若不过滤,
|
* 容器在第一轮找不到别的实现时会把门面自己当候选返回,随后
|
* {@code dataService.selectPatMedInhospList(...)} 变成无限递归
|
* ({@code StackOverflowError})。这是满意度模块<b>实机踩到</b>的同类缺陷。</li>
|
* <li><b>循环依赖</b>:不过滤时 Spring 会在构造本 Bean 的过程中解析到"正在创建的自己",
|
* 直接抛 {@code BeanCurrentlyInCreationException}。实测确认过这一点。</li>
|
* </ol>
|
* <p>
|
* 用 {@code stream()} 而不是 {@code getIfAvailable()}:后者在候选多于一个时抛
|
* {@code NoUniqueBeanDefinitionException},会被吞成 null 并掩盖"有人又加了一个实现"。
|
*/
|
private InhospVisitDataService firstDataServiceOrNull(
|
ObjectProvider<InhospVisitDataService> provider) {
|
if (provider == null) {
|
return null;
|
}
|
try {
|
return provider.stream()
|
.filter(svc -> svc != this)
|
.findFirst()
|
.orElse(null);
|
} catch (Exception e) {
|
log.warn("【出入院随访】获取数据服务失败,基础出入院信息访问将降级:{}", e.toString());
|
return null;
|
}
|
}
|
|
/**
|
* 供<b>测试/非 Spring 环境</b>直接构造(直接给出内部实现,可为 null)。
|
* <p>
|
* 开关取自 {@code sys_config} 的模拟键值,从而保证"开关校验"脚本无需 Spring/数据库即可运行。
|
* <p>
|
* 数据服务不传:测试构造下不提供基础出入院信息访问与宣教单访问
|
* (调用会得到 null / 空集合 / false),保证"开关校验"类测试不必拉起数据库。
|
*/
|
public InhospVisitFacade(InhospVisitProperties properties, InhospVisitApi delegate, String sysConfigValue) {
|
this(properties, new InhospVisitSwitch(properties, sysConfigValue), new FixedProvider(delegate),
|
null, null);
|
}
|
|
/**
|
* 取运行时开关(供拦截器复用同一个实例、也供测试断言)
|
*/
|
public InhospVisitSwitch getInhospVisitSwitch() {
|
return inhospVisitSwitch;
|
}
|
|
/**
|
* 取内部实现;模块关闭、实现缺失、或只找到自己时返回 {@code null}。
|
* <p>
|
* ⚠️ <b>必须排除"自己"</b>:本类自身也实现了 {@link InhospVisitApi},而 Spring 在
|
* 按类型查找候选 Bean 时,若第一轮没找到别的实现(例如 ruoyi-inhospvisit
|
* 没有被打进应用,或将来又有人用条件装配把它摘掉),会<b>把自引用当作兜底候选</b>返回。
|
* 那样 {@code delegateOrNull()} 会拿到 {@code this},随后
|
* {@code delegate.dealOutHospInfo(...)} 就变成无限递归({@code StackOverflowError})。
|
* 这里显式过滤掉自己,把"没有实现"如实视为不可用。
|
* —— 这是满意度模块<b>实机踩到</b>的缺陷。
|
* <p>
|
* ⚠️ <b>本方法不能替代开关判断</b>:开关关闭时 {@link DefaultInhospVisitApi} 依然存在,
|
* 所以调用点一律先判 {@link #isEnabled()}。
|
* <p>
|
* 用 {@code stream()} 而不是 {@code getIfAvailable()}:后者在候选多于一个时抛
|
* {@code NoUniqueBeanDefinitionException}(它继承自 {@code NoSuchBeanDefinitionException}),
|
* 最终会被吞成 null,掩盖"有人又加了一个实现"这种配置问题。
|
*/
|
private InhospVisitApi delegateOrNull() {
|
if (apiProvider == null) {
|
return null;
|
}
|
try {
|
return apiProvider.stream()
|
.filter(api -> api != this)
|
.findFirst()
|
.orElse(null);
|
} catch (Exception e) {
|
// 容器状态异常时按"未启用"处理,绝不让调用方(定时任务、Controller)因为随访模块而失败
|
log.warn("【出入院随访】获取内部实现失败,按未启用处理:{}", e.toString());
|
return null;
|
}
|
}
|
|
@Override
|
public boolean isEnabled() {
|
return inhospVisitSwitch.isEnabled() && delegateOrNull() != null;
|
}
|
|
@Override
|
public int dealOutHospInfo(String config) {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),dealOutHospInfo 跳过。config={}", config);
|
return 0;
|
}
|
return delegateOrNull().dealOutHospInfo(config);
|
}
|
|
@Override
|
public int dealOutHospInfoBySchedule(String config) {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),dealOutHospInfoBySchedule 跳过。config={}", config);
|
return 0;
|
}
|
return delegateOrNull().dealOutHospInfoBySchedule(config);
|
}
|
|
@Override
|
public int addOperationSubTask(String config) {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),addOperationSubTask 跳过。config={}", config);
|
return 0;
|
}
|
return delegateOrNull().addOperationSubTask(config);
|
}
|
|
@Override
|
public int dealOutpatientInfo() {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),dealOutpatientInfo 跳过。");
|
return 0;
|
}
|
return delegateOrNull().dealOutpatientInfo();
|
}
|
|
@Override
|
public int rollTaskGroupCycle() {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),rollTaskGroupCycle 跳过。");
|
return 0;
|
}
|
return delegateOrNull().rollTaskGroupCycle();
|
}
|
|
@Override
|
public com.ruoyi.common.core.service.dto.VisitAgainSubtaskDto buildAgainVisitDraft(String orgid, Long inhospid,
|
Long newTaskId, Long sendstate) {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),buildAgainVisitDraft 返回空结果。"
|
+ "orgid={}, inhospid={}", orgid, inhospid);
|
return emptyAgainDraft("模块未启用");
|
}
|
return delegateOrNull().buildAgainVisitDraft(orgid, inhospid, newTaskId, sendstate);
|
}
|
|
@Override
|
public boolean generatePublicitySubtask(Long taskid, Long patid, Long inhospid, int type, String config) {
|
if (!isEnabled()) {
|
log.warn("【出入院随访】模块未启用(参数配置 inhospvisit.enabled=false),generatePublicitySubtask 跳过。"
|
+ "taskid={}, patid={}, type={}", taskid, patid, type);
|
return false;
|
}
|
return delegateOrNull().generatePublicitySubtask(taskid, patid, inhospid, type, config);
|
}
|
|
// ==================================================================
|
// 基础出入院信息读写(InhospVisitDataService)
|
//
|
// ⚠️ 与上面 6 个随访方法的关键区别:以下方法【不做开关判断】。
|
// 理由见 InhospVisitDataService 类注释 —— 关闭随访生成不该让
|
// HIS 采集/档案汇聚无法写入院记录。
|
//
|
// ⚠️ 每个方法都对 dataService 判空:只有在"测试构造器"下它才是 null;
|
// Spring 环境下由 @Autowired 保证非 null。
|
// 这里返回空值而非抛异常,保证调用方主流程不因本模块而失败。
|
// ==================================================================
|
|
private boolean dataUnavailable(String method) {
|
if (dataService == null) {
|
log.warn("【出入院随访】数据服务不可用(非 Spring 构造或装配缺失),{} 跳过。", method);
|
return true;
|
}
|
return false;
|
}
|
|
@Override
|
public com.ruoyi.inhospvisit.domain.PatMedInhosp selectPatMedInhospByInhospid(Long inhospid) {
|
return dataUnavailable("selectPatMedInhospByInhospid") ? null
|
: dataService.selectPatMedInhospByInhospid(inhospid);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> selectPatMedInhosp(
|
com.ruoyi.inhospvisit.domain.PatMedInhosp patMedInhosp) {
|
return dataUnavailable("selectPatMedInhosp") ? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhosp>emptyList()
|
: dataService.selectPatMedInhosp(patMedInhosp);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> selectOutInhospByPatnoAndOutDate(
|
String patno, java.util.Date dayStart, java.util.Date dayEnd) {
|
return dataUnavailable("selectOutInhospByPatnoAndOutDate")
|
? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhosp>emptyList()
|
: dataService.selectOutInhospByPatnoAndOutDate(patno, dayStart, dayEnd);
|
}
|
|
@Override
|
public String getTagnameBypatid(Long patid) {
|
return dataUnavailable("getTagnameBypatid") ? null : dataService.getTagnameBypatid(patid);
|
}
|
|
@Override
|
public java.util.List<java.util.Map<String, Object>> getTagnameByPatids(java.util.List<Long> patids) {
|
return dataUnavailable("getTagnameByPatids")
|
? java.util.Collections.<java.util.Map<String, Object>>emptyList()
|
: dataService.getTagnameByPatids(patids);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> selectPatMedInhospList(
|
com.ruoyi.inhospvisit.domain.PatMedInhosp patMedInhosp) {
|
return dataUnavailable("selectPatMedInhospList")
|
? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhosp>emptyList()
|
: dataService.selectPatMedInhospList(patMedInhosp);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> selectPatMedInhospListBySerialnum(
|
com.ruoyi.inhospvisit.domain.PatMedInhosp patMedInhosp) {
|
return dataUnavailable("selectPatMedInhospListBySerialnum")
|
? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhosp>emptyList()
|
: dataService.selectPatMedInhospListBySerialnum(patMedInhosp);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> selectPatMedInhospListByCondition(
|
com.ruoyi.inhospvisit.domain.PatMedInhospVO patMedInhospVO) {
|
return dataUnavailable("selectPatMedInhospListByCondition")
|
? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhosp>emptyList()
|
: dataService.selectPatMedInhospListByCondition(patMedInhospVO);
|
}
|
|
@Override
|
public com.ruoyi.common.core.service.dto.PatMedRes selectPatMedInhospCount(
|
com.ruoyi.common.core.service.dto.PatMedReq patMedReq) {
|
return dataUnavailable("selectPatMedInhospCount") ? null : dataService.selectPatMedInhospCount(patMedReq);
|
}
|
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> selectNeedProcessList() {
|
return dataUnavailable("selectNeedProcessList")
|
? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhosp>emptyList()
|
: dataService.selectNeedProcessList();
|
}
|
|
/**
|
* 查询患者住院记录(通过入院申请单信息)。
|
* <p>
|
* ⚠️ 降级时返回<b>空列表</b>(不是 null)—— 调用方的分页逻辑对 null 与空列表处理相同,
|
* 但空列表能避免调用方额外判空。注意本方法在<b>正常</b>路径下也可能返回 {@code null}
|
* (原实现的反向判断缺陷,见 {@code InhospVisitDataService} 的说明),那是业务行为,不是降级。
|
*/
|
@Override
|
public java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhospDTO> selectPatMedInhospByApplication(
|
com.ruoyi.inhospvisit.domain.PatMedInhosp patMedInhosp) {
|
return dataUnavailable("selectPatMedInhospByApplication")
|
? java.util.Collections.<com.ruoyi.inhospvisit.domain.PatMedInhospDTO>emptyList()
|
: dataService.selectPatMedInhospByApplication(patMedInhosp);
|
}
|
|
@Override
|
public int insertPatMedInhosp(com.ruoyi.inhospvisit.domain.PatMedInhosp patMedInhosp) {
|
return dataUnavailable("insertPatMedInhosp") ? 0 : dataService.insertPatMedInhosp(patMedInhosp);
|
}
|
|
@Override
|
public int insertPatMedInhospBatch(java.util.List<com.ruoyi.inhospvisit.domain.PatMedInhosp> list) {
|
return dataUnavailable("insertPatMedInhospBatch") ? 0 : dataService.insertPatMedInhospBatch(list);
|
}
|
|
@Override
|
public int updatePatMedInhosp(com.ruoyi.inhospvisit.domain.PatMedInhosp patMedInhosp) {
|
return dataUnavailable("updatePatMedInhosp") ? 0 : dataService.updatePatMedInhosp(patMedInhosp);
|
}
|
|
@Override
|
public int deletePatMedInhospByInhospid(Long inhospid) {
|
return dataUnavailable("deletePatMedInhospByInhospid") ? 0 : dataService.deletePatMedInhospByInhospid(inhospid);
|
}
|
|
@Override
|
public int deletePatMedInhospByInhospno(String inhospno) {
|
return dataUnavailable("deletePatMedInhospByInhospno") ? 0 : dataService.deletePatMedInhospByInhospno(inhospno);
|
}
|
|
@Override
|
public int deletePatMedInhospByInhospids(Long[] inhospids) {
|
return dataUnavailable("deletePatMedInhospByInhospids") ? 0
|
: dataService.deletePatMedInhospByInhospids(inhospids);
|
}
|
|
/**
|
* 空结果(键与"启用但组装失败"时一致,保证调用方不会 NPE)
|
*/
|
public static com.ruoyi.common.core.service.dto.VisitAgainSubtaskDto emptyAgainDraft(String reason) {
|
com.ruoyi.common.core.service.dto.VisitAgainSubtaskDto dto =
|
new com.ruoyi.common.core.service.dto.VisitAgainSubtaskDto();
|
dto.setDraft(null);
|
dto.setInhospFound(false);
|
dto.setMissReason(reason);
|
return dto;
|
}
|
|
/**
|
* 固定的 {@code ObjectProvider} 实现:仅用于非 Spring 环境/测试。
|
*/
|
private static final class FixedProvider implements ObjectProvider<InhospVisitApi> {
|
|
private final InhospVisitApi api;
|
|
private FixedProvider(InhospVisitApi api) {
|
this.api = api;
|
}
|
|
@Override
|
public InhospVisitApi getObject(Object... args) {
|
return api;
|
}
|
|
@Override
|
public InhospVisitApi getIfAvailable() {
|
return api;
|
}
|
|
@Override
|
public InhospVisitApi getIfUnique() {
|
return api;
|
}
|
|
@Override
|
public InhospVisitApi getObject() {
|
return api;
|
}
|
|
@Override
|
public java.util.stream.Stream<InhospVisitApi> stream() {
|
return api == null ? java.util.stream.Stream.empty() : java.util.stream.Stream.of(api);
|
}
|
}
|
}
|