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} 的<b>本模块实现</b>。
|
*
|
* <h3>它取代了什么</h3>
|
* 在 {@code ruoyi-othervisit} 建好之前,{@link OtherVisitApi} 只有 smartor 侧的
|
* 过渡桥接 {@code OtherVisitApiBridge}。手术随访的实现搬进本模块后,
|
* 由本类接管 —— 这正是那个 Bridge 的类注释里预告的"将来动作"。
|
*
|
* <h3>⚠️ 本类两个方法<b>本次都还委托 smartor</b>(刻意,不是漏做)</h3>
|
* <table border="1">
|
* <tr><th>接口方法</th><th>原实现位置</th><th>为什么本次不搬</th></tr>
|
* <tr><td>{@link #addOperationSubTask(String)}</td>
|
* <td>{@code PatMedInhospServiceImpl#addOperationSubTask} L1247-1316</td>
|
* <td>它是<b>手术等级({@code oplevelcode})+ 离院科室/病区维度</b>的扫描,
|
* 属"出院随访里混着的手术分支",且依赖
|
* {@code ServiceTaskoperMapper}(仍在 smartor)与
|
* {@code writeInSubTaskForOp}(依赖 {@code ScheduleSubtaskBuilder})。</td></tr>
|
* <tr><td>{@link #dealOutHospInfoBySchedule(String)}</td>
|
* <td>同文件 L380-614</td>
|
* <td>它的<b>非手术分支</b>与"HIS 自动纳入"、"前端手动勾选"共用
|
* {@code ScheduleSubtaskBuilder}。搬它得连 builder 一起搬 ——
|
* 那是独立的一次改造。</td></tr>
|
* </table>
|
*
|
* <h3>那本模块搬了什么?</h3>
|
* <b>手术编码({@code opcode})维度</b>的那条扫描:
|
* {@code PatMedOperationServiceImpl#dealOperationInfo}(原 L107-149)。
|
* 它的入口<b>不走</b>本接口,而是 {@link OtherVisitFacade#dealOperationInfo()} ——
|
* 调用方是 {@code RyTask#dealOperationInfo}(定时任务),已直接改走门面。
|
* 之所以不塞进本接口,是因为两者语义不同:
|
* 接口上那两个是"出院/任务组流程里的手术分支",而这条是"手术记录自身的扫描"。
|
*
|
* <h3>⚠️ 为什么编译期看不到 smartor</h3>
|
* 依赖方向是 smartor → ruoyi-othervisit,反过来会形成 Maven 循环依赖,直接构建失败。
|
* 所以这里用 {@code ObjectProvider<OtherVisitApi>} 在<b>运行时</b>按类型惰性查找
|
* smartor 侧那个承接实现,并<b>排除本类自己</b>(否则会自己调自己 → {@code StackOverflowError})。
|
* 取不到就打 WARN 并返回安全值,绝不让定时任务抛异常。
|
*
|
* @see OtherVisitApi
|
*/
|
@Slf4j
|
@Component
|
public class OtherVisitApiImpl implements OtherVisitApi {
|
|
/**
|
* smartor 侧的过渡承接({@code com.smartor.service.impl.bridge.OtherVisitApiBridge})。
|
* <p>
|
* ⚠️ 类型参数刻意写成 {@link OtherVisitApi} 而<b>不是</b>那个具体类:
|
* 本模块编译期看不到 smartor 的类型(也不允许看到)。
|
*/
|
@Autowired
|
private ObjectProvider<OtherVisitApi> 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 侧那个承接实现。
|
* <p>
|
* ⚠️ <b>必须排除本类</b>:本类也实现了 {@link OtherVisitApi},
|
* 若不过滤就会取到自己,形成无限递归。
|
* ⚠️ 用 {@code stream()} 而不是 {@code getIfAvailable()}:
|
* 后者在存在多个候选时行为不确定,而这里天然有<b>两个</b>候选实现(本类 + 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;
|
}
|
}
|
}
|