package com.ruoyi.othervisit.api;
import com.ruoyi.common.core.service.OtherVisitApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* {@link OtherVisitApi} 的本模块实现。
*
*
它取代了什么
* 在 {@code ruoyi-othervisit} 建好之前,{@link OtherVisitApi} 只有 smartor 侧的
* 过渡桥接 {@code OtherVisitApiBridge}。手术随访的实现搬进本模块后,
* 由本类接管 —— 这正是那个 Bridge 的类注释里预告的"将来动作"。
*
* ⚠️ 本类两个方法本次都还委托 smartor(刻意,不是漏做)
*
* | 接口方法 | 原实现位置 | 为什么本次不搬 |
* | {@link #addOperationSubTask(String)} |
* {@code PatMedInhospServiceImpl#addOperationSubTask} L1247-1316 |
* 它是手术等级({@code oplevelcode})+ 离院科室/病区维度的扫描,
* 属"出院随访里混着的手术分支",且依赖
* {@code ServiceTaskoperMapper}(仍在 smartor)与
* {@code writeInSubTaskForOp}(依赖 {@code ScheduleSubtaskBuilder})。 |
* | {@link #dealOutHospInfoBySchedule(String)} |
* 同文件 L380-614 |
* 它的非手术分支与"HIS 自动纳入"、"前端手动勾选"共用
* {@code ScheduleSubtaskBuilder}。搬它得连 builder 一起搬 ——
* 那是独立的一次改造。 |
*
*
* 那本模块搬了什么?
* 手术编码({@code opcode})维度的那条扫描:
* {@code PatMedOperationServiceImpl#dealOperationInfo}(原 L107-149)。
* 它的入口不走本接口,而是 {@link OtherVisitFacade#dealOperationInfo()} ——
* 调用方是 {@code RyTask#dealOperationInfo}(定时任务),已直接改走门面。
* 之所以不塞进本接口,是因为两者语义不同:
* 接口上那两个是"出院/任务组流程里的手术分支",而这条是"手术记录自身的扫描"。
*
* ⚠️ 为什么编译期看不到 smartor
* 依赖方向是 smartor → ruoyi-othervisit,反过来会形成 Maven 循环依赖,直接构建失败。
* 所以这里用 {@code ObjectProvider} 在运行时按类型惰性查找
* smartor 侧那个承接实现,并排除本类自己(否则会自己调自己 → {@code StackOverflowError})。
* 取不到就打 WARN 并返回安全值,绝不让定时任务抛异常。
*
* @see OtherVisitApi
*/
@Slf4j
@Component
public class OtherVisitApiImpl implements OtherVisitApi {
/**
* smartor 侧的过渡承接({@code com.smartor.service.impl.bridge.OtherVisitApiBridge})。
*
* ⚠️ 类型参数刻意写成 {@link OtherVisitApi} 而不是那个具体类:
* 本模块编译期看不到 smartor 的类型(也不允许看到)。
*/
@Autowired
private ObjectProvider otherVisitApiProvider;
/**
* 手术随访扫描(手术等级 + 离院科室/病区维度)—— 本次仍委托 smartor。
*
* @param config {@code sys_config: visit.early.day} 的值,可能为 null
* @return 处理的手术记录数;承接实现不可用时返回 0
*/
@Override
public int addOperationSubTask(String config) {
OtherVisitApi delegate = findExternalDelegate();
if (delegate == null) {
log.warn("【手术随访】addOperationSubTask 的 smartor 侧承接实现不可用(未打进应用或未装配),本次跳过。");
return 0;
}
return delegate.addOperationSubTask(config);
}
/**
* 任务组(appltype=5)首轮纳入 —— 本次仍委托 smartor。
*
* @param config {@code sys_config: visit.early.day}
* @return 原实现固定返回 1;承接实现不可用时返回 0
*/
@Override
public int dealOutHospInfoBySchedule(String config) {
OtherVisitApi delegate = findExternalDelegate();
if (delegate == null) {
log.warn("【手术随访】dealOutHospInfoBySchedule 的 smartor 侧承接实现不可用(未打进应用或未装配),本次跳过。");
return 0;
}
return delegate.dealOutHospInfoBySchedule(config);
}
/**
* 找 smartor 侧那个承接实现。
*
* ⚠️ 必须排除本类:本类也实现了 {@link OtherVisitApi},
* 若不过滤就会取到自己,形成无限递归。
* ⚠️ 用 {@code stream()} 而不是 {@code getIfAvailable()}:
* 后者在存在多个候选时行为不确定,而这里天然有两个候选实现(本类 + smartor 桥接)。
*/
private OtherVisitApi findExternalDelegate() {
if (otherVisitApiProvider == null) {
return null;
}
try {
return otherVisitApiProvider.stream()
.filter(api -> api != this)
.findFirst()
.orElse(null);
} catch (Exception e) {
log.warn("【手术随访】获取其它随访承接实现失败,按不可用处理:{}", e.toString());
return null;
}
}
}