liusheng
5 天以前 cc479e6a056785103996cc7ea67dbd5faa3e800e
smartor/src/main/java/com/smartor/service/impl/ServiceSLTDHealthcareRecordServiceImpl.java
@@ -10,12 +10,18 @@
import com.ruoyi.common.core.domain.entity.SysUserRole;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.service.dto.InhospPositionRecord;
import com.smartor.common.enums.EmergencyLevelEnum;
import com.smartor.common.enums.ImportFlagEnum;
import com.ruoyi.common.utils.http.HttpUtils;
import com.smartor.common.DistinctByProperty;
import com.smartor.domain.*;
import com.ruoyi.outpatientvisit.domain.PatMedOuthospError;
import com.ruoyi.outpatientvisit.domain.PatMedOuthosp;
import com.ruoyi.inhospvisit.api.InhospVisitFacade;
import com.ruoyi.inhospvisit.domain.PatMedInhosp;
import com.smartor.mapper.*;
import com.ruoyi.outpatientvisit.mapper.PatMedOuthospErrorMapper;
import com.smartor.service.IPatArchiveService;
import com.smartor.service.IPatMedInhospService;
import com.smartor.service.IPatMedOuthospService;
@@ -37,12 +43,33 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.ruoyi.common.core.domain.entity.PatArchive;
import com.ruoyi.task.domain.ServiceSubtask;
import com.ruoyi.task.mapper.ServiceSubtaskMapper;
import com.ruoyi.task.service.impl.ServiceSubtaskServiceImpl;
@Slf4j
@Service
public class ServiceSLTDHealthcareRecordServiceImpl implements IServiceSLTDHealthcareRecordService {
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    /**
     * 在院患者当前位置查询地址(网关根路径 {@code sltd_pub_path} + 固定后缀)。
     * <p>
     * 与"入院采集"是<b>同一个接口</b>({@code queryHealthcareRecordList} 用的也是它),
     * 区别只是本方法按 {@code healthcareRecordNo} 单查、只取位置字段、不落库。
     */
    private static final String INHOSP_POSITION_PATH =
            "/osj/hbos-thirdparty-integration/standard/common/healthcareRecord/dtcQueryHealthcareRecordList";
    /**
     * 当前位置查询的连接/读超时:一轮要按患者调用几千次,
     * 不能让一次无响应把采集线程无限期挂住({@code HttpUtils} 老方法没有超时)
     */
    private static final int INHOSP_POSITION_CONNECT_TIMEOUT_MS = 5000;
    private static final int INHOSP_POSITION_READ_TIMEOUT_MS = 15000;
    @Autowired
    private IPatArchiveService patArchiveService;
@@ -91,7 +118,7 @@
    @Autowired
    private ServiceSubtaskMapper serviceSubtaskMapper;
    @Autowired
    private PatMedInhospMapper patMedInhospMapper;
    private InhospVisitFacade inhospVisitFacade;
    @Autowired
    private PatMedOuthospErrorMapper patMedOuthospErrorMapper;
@@ -415,6 +442,47 @@
        }
        return true;
    }
    @Override
    public List<InhospPositionRecord> queryInhospPosition(ServiceSLTDInhospReqVO reqVO) {
        // 与"入院采集"共用同一套入参构造:orgId + campusIds + statusList + healthcareRecordNo
        Map<String, Object> requestParams = buildRequestParams(reqVO);
        Map<String, String> headers = buildRequestHeaders();
        String url = sltdPubPath + INHOSP_POSITION_PATH;
        String result = HttpUtils.sendPostByHeader(url, new Gson().toJson(requestParams), headers,
                INHOSP_POSITION_CONNECT_TIMEOUT_MS, INHOSP_POSITION_READ_TIMEOUT_MS);
        if (StringUtils.isEmpty(result)) {
            // sendPostByHeader 把异常吞掉后返回空串:这里绝不能当成"该患者已不在院",
            // 否则接口整体不可用时会被记成"几千个患者都出院了",与真相反。
            throw new RuntimeException("查询在院患者当前位置接口无响应,healthcareRecordNo=" + reqVO.getHealthcareRecordNo());
        }
        // getDataList 在返回码非 200 时抛 RuntimeException;data 为 [](该患者已不在入院状态)时返回空列表
        List<Map<String, Object>> dataList = getDataList(result, 1);
        List<InhospPositionRecord> records = new ArrayList<>(dataList.size());
        for (Map<String, Object> dataItem : dataList) {
            records.add(convertToInhospPosition(dataItem));
        }
        return records;
    }
    /**
     * 健康记录 JSON → 契约 DTO 的逐字段搬运(只取"当前位置"要用的字段)。
     * <p>
     * 一律走 {@code getStringValue} / {@code getLongValue}:接口对空值可能返回 {@code null}、
     * {@code ""} 甚至缺字段,直接让 Gson 反序列化到 Long 字段会在空串上抛 NumberFormatException。
     */
    private InhospPositionRecord convertToInhospPosition(Map<String, Object> dataItem) {
        InhospPositionRecord record = new InhospPositionRecord();
        record.setHealthcareRecordNo(getStringValue(dataItem, "healthcareRecordNo"));
        record.setPatientName(getStringValue(dataItem, "patientName"));
        record.setDeptId(getLongValue(dataItem, "deptId"));
        record.setDeptName(getStringValue(dataItem, "deptName"));
        record.setAreaId(getLongValue(dataItem, "areaId"));
        record.setAreaName(getStringValue(dataItem, "areaName"));
        record.setBedNumber(getStringValue(dataItem, "bedNumber"));
        record.setHealthcareRecordStatus(getStringValue(dataItem, "healthcareRecordStatus"));
        return record;
    }
    private String determineCry(ServiceSLTDInhospReqVO reqVO) {
@@ -852,10 +920,22 @@
    }
    private Boolean inHospitalDate(List<ServiceSLTDInhospResDTO> resultList, String cry) {
        int failCount = 0;
        for (ServiceSLTDInhospResDTO dto : resultList) {
            if (Objects.isNull(dto)) continue;
            PatArchive patArchive = processPatientArchive(dto);
            processPatientInhospInfo(dto, patArchive, cry);
            try {
                PatArchive patArchive = processPatientArchive(dto);
                processPatientInhospInfo(dto, patArchive, cry);
            } catch (Exception e) {
                failCount++;
                log.error("【inHospitalDate】单条记录处理失败,已跳过继续采集。state={}, serialnum={}, patname={}, patno={}, orgid={}, campusId={}",
                        cry, dto.getHealthcareRecordNo(), dto.getPatientName(), dto.getMedicalRecordNo(),
                        dto.getOrgId(), dto.getCampusId(), e);
            }
        }
        if (failCount > 0) {
            log.warn("【inHospitalDate】本页共{}条,失败{}条已跳过,其余{}条处理完成,state={}",
                    resultList.size(), failCount, resultList.size() - failCount, cry);
        }
        return true;
    }
@@ -906,7 +986,7 @@
                            if (pmIn.getStarttime() != null) {
                                Date dayStart = DateUtils.truncate(pmIn.getStarttime(), Calendar.DAY_OF_MONTH);
                                Date dayEnd = DateUtils.addDays(dayStart, 1);
                                List<PatMedInhosp> outInhosps = patMedInhospMapper.selectOutInhospByPatnoAndOutDate(
                                List<PatMedInhosp> outInhosps = inhospVisitFacade.selectOutInhospByPatnoAndOutDate(
                                        StringUtils.trim(pmIn.getPatno()), dayStart, dayEnd);
                                if (CollectionUtils.isNotEmpty(outInhosps)) {
                                    //存在出院记录,说明该患者是再入院,把上一次出院产生的子任务改成不执行