| | |
| | | import com.ruoyi.othervisit.api.OtherVisitFacade; |
| | | import com.ruoyi.inhospvisit.api.InhospVisitFacade; |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.google.gson.Gson; |
| | | import com.google.gson.reflect.TypeToken; |
| | | import com.ruoyi.common.core.domain.entity.SysDept; |
| | |
| | | import com.ruoyi.common.utils.DtoConversionUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.http.HttpUtils; |
| | | import com.ruoyi.system.service.ISysConfigService; |
| | | import com.smartor.domain.*; |
| | | import com.smartor.mapper.*; |
| | | import com.smartor.service.IPatMedOuthospService; |
| | | import com.smartor.service.IPatSpecificArchiveGenerateService; |
| | | import com.smartor.service.IServiceExternalService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.collections4.CollectionUtils; |
| | |
| | | import com.ruoyi.task.domain.entity.ServiceSubtaskEntity; |
| | | import com.ruoyi.task.domain.ServiceSubtask; |
| | | import com.ruoyi.task.mapper.ServiceSubtaskMapper; |
| | | import com.ruoyi.patarchive.mapper.PatArchiveMapper; |
| | | import com.ruoyi.patarchive.mapper.PatArchivecontactMapper; |
| | | import com.ruoyi.common.core.domain.entity.Icd10; |
| | | import com.ruoyi.common.mapper.Icd10Mapper; |
| | | import com.ruoyi.system.mapper.ext.SysUser2Mapper; |
| | | import com.ruoyi.system.mapper.ext.SysDept2Mapper; |
| | | import com.ruoyi.system.mapper.ext.SysUserDeptMapper; |
| | | /** |
| | | * 主键Service业务层处理 |
| | | * |
| | |
| | | @Slf4j |
| | | @Service |
| | | public class ServiceExternalServiceImpl implements IServiceExternalService { |
| | | /** |
| | | * 龙泉人民医院机构ID |
| | | */ |
| | | private static final String LONGQUAN_PEOPLE_HOSPITAL_ORG_ID = "47240004533118111A1001"; |
| | | |
| | | @Autowired |
| | | private SysDept2Mapper sysDeptMapper; |
| | | |
| | |
| | | private Icd10Mapper icd10Mapper; |
| | | @Autowired |
| | | private IPatMedOuthospService patMedOuthospService; |
| | | @Autowired |
| | | private ISysConfigService configService; |
| | | @Autowired |
| | | private IPatSpecificArchiveGenerateService patSpecificArchiveGenerateService; |
| | | @Autowired |
| | | private PatMedOuthospMapper patMedOuthospMapper; |
| | | @Autowired |
| | |
| | | patMedOuthospService.dealPatMedOuthosp(patMedOuthosp, visitTimeNum); |
| | | } |
| | | |
| | | genePatSpecificArchive(patMedOuthosp, patArchive); |
| | | |
| | | if (i > 0) { |
| | | return true; |
| | | } |
| | |
| | | } else { |
| | | patMedInhosp.setCreateTime(new Date()); |
| | | i = inhospVisitFacade.insertPatMedInhosp(patMedInhosp); |
| | | if (i == 1) { |
| | | //龙泉人民医院:新增住院信息时处理患者再入院 |
| | | stopReadmissionFollowUpTasks(patMedInhosp); |
| | | } |
| | | } |
| | | if (i == 1) return true; |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 患者再入院处理:患者再次入院后,上一次出院生成的待执行长期随访任务不再执行。 |
| | | * 目前仅对龙泉人民医院生效,避免影响其他机构。 |
| | | * |
| | | * @param patMedInhosp 本次新增的住院信息 |
| | | */ |
| | | private void stopReadmissionFollowUpTasks(PatMedInhosp patMedInhosp) { |
| | | if (!LONGQUAN_PEOPLE_HOSPITAL_ORG_ID.equals(patMedInhosp.getOrgid())) { |
| | | return; |
| | | } |
| | | if (Objects.isNull(patMedInhosp.getPatid()) || Objects.isNull(patMedInhosp.getStarttime())) { |
| | | log.warn("龙泉人民医院患者再入院处理跳过,patid或入院时间为空,inhospno={}", patMedInhosp.getInhospno()); |
| | | return; |
| | | } |
| | | try { |
| | | ServiceSubtaskEntity subtask = new ServiceSubtaskEntity(); |
| | | subtask.setPatid(patMedInhosp.getPatid()); |
| | | subtask.setOrgid(LONGQUAN_PEOPLE_HOSPITAL_ORG_ID); |
| | | subtask.setSendstate(2L); |
| | | List<ServiceSubtask> serviceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(subtask); |
| | | if (CollectionUtils.isEmpty(serviceSubtaskList)) { |
| | | return; |
| | | } |
| | | int stopCount = 0; |
| | | for (ServiceSubtask serviceSubtask : serviceSubtaskList) { |
| | | //不是长期任务,不处理 |
| | | if (Objects.isNull(serviceSubtask.getLongSendTime())) { |
| | | continue; |
| | | } |
| | | //出院时间晚于或等于本次入院时间的任务,不属于本次入院前的待随访任务 |
| | | if (Objects.isNull(serviceSubtask.getEndtime()) |
| | | || !serviceSubtask.getEndtime().before(patMedInhosp.getStarttime())) { |
| | | continue; |
| | | } |
| | | serviceSubtask.setSendstate(4L); |
| | | serviceSubtask.setIsVisitAgain(2); |
| | | serviceSubtask.setResult("error"); |
| | | serviceSubtask.setRemark(StringUtils.isNotEmpty(serviceSubtask.getRemark()) |
| | | ? serviceSubtask.getRemark() + ";患者再入院" : "患者再入院"); |
| | | serviceSubtask.setUpdateTime(new Date()); |
| | | if (Boolean.TRUE.equals(serviceSubtaskMapper.updateServiceSubtask(serviceSubtask))) { |
| | | stopCount++; |
| | | } |
| | | } |
| | | log.info("龙泉人民医院患者再入院处理完成,patid={},本次入院时间={},停止待执行长期任务{}条", |
| | | patMedInhosp.getPatid(), patMedInhosp.getStarttime(), stopCount); |
| | | } catch (Exception e) { |
| | | //再入院任务处理失败不影响本次住院信息入库 |
| | | log.error("龙泉人民医院患者再入院处理异常,patid={},inhospno={}", |
| | | patMedInhosp.getPatid(), patMedInhosp.getInhospno(), e); |
| | | } |
| | | } |
| | | |
| | | //新增随访任务同步 |
| | |
| | | } |
| | | |
| | | //检查详情添加 |
| | | @SuppressWarnings("unchecked") |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean addInspectBGService(Map dataMap) { |
| | | log.info("ServiceExternalServiceImpl---addInspectBGService的新增的值为:{}", dataMap); |
| | | Map xiaoXiTou = (Map) dataMap.get("XiaoXiTou"); |
| | | Map yeWuXX = (Map) dataMap.get("YeWuXX"); |
| | | Map<String, Object> BingRenXX = ObjectUtils.isNotEmpty(yeWuXX) ? (Map<String, Object>) yeWuXX.get("BingRenXX") : null; |
| | | Map<String, Object> JianChaBG = ObjectUtils.isNotEmpty(yeWuXX) ? (Map<String, Object>) yeWuXX.get("JianChaBG") : null; |
| | | List<HashMap<String, Object>> JianChaBWList = ObjectUtils.isNotEmpty(JianChaBG) ? (List<HashMap<String, Object>>) JianChaBG.get("JianChaBWList") : null; |
| | | if (ObjectUtils.isEmpty(BingRenXX)) { |
| | | throw new BaseException("检查报告同步失败:BingRenXX不能为空"); |
| | | } |
| | | if (ObjectUtils.isEmpty(JianChaBG)) { |
| | | throw new BaseException("检查报告同步失败:JianChaBG不能为空"); |
| | | } |
| | | |
| | | // 机构优先取消息头,其次取患者信息,和检查申请补建逻辑保持一致 |
| | | String orgid = ObjectUtils.isNotEmpty(xiaoXiTou) ? getMapValue(xiaoXiTou, "FaSongJGID") : null; |
| | | if (StringUtils.isBlank(orgid)) { |
| | | orgid = getMapValue(BingRenXX, "ZuZhiJGID"); |
| | | } |
| | | String bingAnHao = getMapValue(BingRenXX, "BingAnHao"); |
| | | String bingRenID = getMapValue(BingRenXX, "BingRenID"); |
| | | String xingMing = getMapValue(BingRenXX, "XingMing"); |
| | | String shenQingDID = getMapValue(JianChaBG, "ShenQingDID"); |
| | | if (StringUtils.isBlank(orgid) || StringUtils.isBlank(bingAnHao) || StringUtils.isBlank(bingRenID) |
| | | || StringUtils.isBlank(xingMing) || StringUtils.isBlank(shenQingDID)) { |
| | | throw new BaseException("检查报告同步失败:BingRenXX.ZuZhiJGID/BingAnHao/BingRenID/XingMing、JianChaBG.ShenQingDID不能为空"); |
| | | } |
| | | |
| | | PatMedInspection patMedInspection = new PatMedInspection(); |
| | | PatMedInspectionItem patMedInspectionItem = new PatMedInspectionItem(); |
| | | patMedInspection.setOrgid(BingRenXX.get("ZuZhiJGID").toString()); |
| | | patMedInspection.setOrgid(orgid); |
| | | //丽水无院区,默认值是 1 |
| | | patMedInspection.setCampusid("1"); |
| | | patMedInspection.setInhospno(BingRenXX.get("BingAnHao").toString()); |
| | | patMedInspection.setPatidHis(BingRenXX.get("BingRenID").toString()); |
| | | patMedInspection.setPatname(BingRenXX.get("XingMing").toString()); |
| | | patMedInspection.setAppliyid(JianChaBG.get("ShenQingDID").toString()); |
| | | patMedInspection.setInhospno(bingAnHao); |
| | | patMedInspection.setPatidHis(bingRenID); |
| | | patMedInspection.setPatname(xingMing); |
| | | patMedInspection.setAppliyid(shenQingDID); |
| | | //查找患者检查检验信息,如果无,进行新加 |
| | | List<PatMedInspection> patMedInspections = patMedInspectionMapper.selectPatMedInspectionList(patMedInspection); |
| | | if (CollectionUtils.isNotEmpty(patMedInspections)) { |
| | | patMedInspectionItem.setInspectionid(patMedInspections.get(0).getId().intValue()); |
| | | } else { |
| | | if (CollectionUtils.isEmpty(patMedInspections)) { |
| | | addInspectService(dataMap); |
| | | List<PatMedInspection> patMedInspections2 = patMedInspectionMapper.selectPatMedInspectionList(patMedInspection); |
| | | patMedInspectionItem.setInspectionid(patMedInspections2.get(0).getId().intValue()); |
| | | patMedInspections = patMedInspectionMapper.selectPatMedInspectionList(patMedInspection); |
| | | if (CollectionUtils.isEmpty(patMedInspections)) { |
| | | throw new BaseException("检查报告同步失败:未找到或创建检查主记录,ShenQingDID=" + shenQingDID); |
| | | } |
| | | } |
| | | patMedInspectionItem.setInspectionid(patMedInspections.get(0).getId().intValue()); |
| | | //检查检验报告数据处理 |
| | | patMedInspectionItem.setOrgid(BingRenXX.get("ZuZhiJGID").toString()); |
| | | patMedInspectionItem.setOrgid(orgid); |
| | | //丽水无院区,默认值是 1 |
| | | patMedInspectionItem.setCampusid("1"); |
| | | List<PatMedInspectionItem> patMedInspectionItems = patMedInspectionItemMapper.selectPatMedInspectionItemList(patMedInspectionItem); |
| | | if (ObjectUtils.isNotEmpty(JianChaBG)) { |
| | | patMedInspectionItem.setInspectionName(JianChaBG.get("JianChaHao").toString()); |
| | | patMedInspectionItem.setReportid(JianChaBG.get("JianChaHao").toString()); |
| | | patMedInspectionItem.setStatuscode(JianChaBG.get("DangQianZTDM").toString()); |
| | | patMedInspectionItem.setStatusname(JianChaBG.get("DangQianZTMC").toString()); |
| | | patMedInspectionItem.setReportid(JianChaBG.get("BaoGaoRID").toString()); |
| | | patMedInspectionItem.setReportername(JianChaBG.get("BaoGaoRXM").toString()); |
| | | patMedInspectionItem.setDiagimpression(JianChaBG.get("ZhenDuanYX").toString()); |
| | | patMedInspectionItem.setDiagfindings(JianChaBG.get("ZhenDuanSJ").toString()); |
| | | patMedInspectionItem.setDiagsuggestion(JianChaBG.get("ZhenDuanJY").toString()); |
| | | patMedInspectionItem.setReporturl(JianChaBG.get("BaoGaoYXDZ").toString()); |
| | | patMedInspectionItem.setCriticalFlag(Integer.valueOf(JianChaBG.get("WeiJiZBZ").toString())); |
| | | patMedInspectionItem.setCriticalContent(JianChaBG.get("WeiJiZNR").toString()); |
| | | patMedInspectionItem.setReportdeptid(JianChaBG.get("BaoGaoKSID").toString()); |
| | | patMedInspectionItem.setReportdeptname(JianChaBG.get("BaoGaoKSMC").toString()); |
| | | patMedInspectionItem.setResultcode(JianChaBG.get("JianChaJGDM").toString()); |
| | | patMedInspectionItem.setResultname(JianChaBG.get("JianChaJGMC").toString()); |
| | | if (ObjectUtils.isNotEmpty(JianChaBG.get("BaoGaoSJ"))) { |
| | | try { |
| | | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | patMedInspection.setOpendate(simpleDateFormat.parse(JianChaBG.get("BaoGaoSJ").toString())); |
| | | } catch (ParseException e) { |
| | | e.printStackTrace(); |
| | | |
| | | // 兼容 PACS 实际报文:报告人、报告时间、报告地址等字段名与标准报文存在差异 |
| | | String jianChaHao = getMapValue(JianChaBG, "JianChaHao"); |
| | | String reportId = getMapValue(JianChaBG, "BaoGaoID"); |
| | | if (StringUtils.isBlank(reportId)) { |
| | | reportId = getMapValue(JianChaBG, "BaoGaoRID"); |
| | | } |
| | | if (StringUtils.isBlank(reportId)) { |
| | | reportId = jianChaHao; |
| | | } |
| | | String inspectionName = StringUtils.isNotBlank(jianChaHao) ? jianChaHao : reportId; |
| | | if (StringUtils.isBlank(inspectionName)) { |
| | | inspectionName = shenQingDID; |
| | | } |
| | | String reporterId = getMapValue(JianChaBG, "BaoGaoRID", "ZhiXingRID", "KaiDanRID"); |
| | | String reporterName = getMapValue(JianChaBG, "BaoGaoRXM", "ZhiXingRXM", "KaiDanRXM"); |
| | | String reportUrl = getMapValue(JianChaBG, "BaoGaoYXDZ", "TuWenBGXZDZ", "PDFurl"); |
| | | String reportDateStr = getMapValue(JianChaBG, "BaoGaoSJ", "ZhiXingSJ"); |
| | | |
| | | patMedInspectionItem.setInspectionName(inspectionName); |
| | | patMedInspectionItem.setReportid(reportId); |
| | | patMedInspectionItem.setStatuscode(getMapValue(JianChaBG, "DangQianZTDM")); |
| | | patMedInspectionItem.setStatusname(getMapValue(JianChaBG, "DangQianZTMC")); |
| | | patMedInspectionItem.setReporterid(reporterId); |
| | | patMedInspectionItem.setReportername(reporterName); |
| | | patMedInspectionItem.setDiagimpression(getMapValue(JianChaBG, "ZhenDuanYX")); |
| | | patMedInspectionItem.setDiagfindings(getMapValue(JianChaBG, "ZhenDuanSJ")); |
| | | patMedInspectionItem.setDiagsuggestion(getMapValue(JianChaBG, "ZhenDuanJY")); |
| | | patMedInspectionItem.setReporturl(reportUrl); |
| | | patMedInspectionItem.setCriticalFlag(parseInteger(getMapValue(JianChaBG, "WeiJiZBZ"))); |
| | | patMedInspectionItem.setCriticalContent(getMapValue(JianChaBG, "WeiJiZNR")); |
| | | patMedInspectionItem.setReportdeptid(getMapValue(JianChaBG, "BaoGaoKSID")); |
| | | patMedInspectionItem.setReportdeptname(getMapValue(JianChaBG, "BaoGaoKSMC")); |
| | | patMedInspectionItem.setResultcode(getMapValue(JianChaBG, "JianChaJGDM")); |
| | | patMedInspectionItem.setResultname(getMapValue(JianChaBG, "JianChaJGMC")); |
| | | Date reportDate = parseDateTime(reportDateStr); |
| | | if (reportDate != null) { |
| | | patMedInspectionItem.setReportdate(reportDate); |
| | | } |
| | | |
| | | // 同一检查下可能存在多条报告明细,优先按报告ID、检查号匹配,避免更新错行 |
| | | PatMedInspectionItem existingItem = null; |
| | | if (CollectionUtils.isNotEmpty(patMedInspectionItems)) { |
| | | for (PatMedInspectionItem item : patMedInspectionItems) { |
| | | if (StringUtils.isNotBlank(reportId) && reportId.equals(item.getReportid())) { |
| | | existingItem = item; |
| | | break; |
| | | } |
| | | } |
| | | if (existingItem == null) { |
| | | for (PatMedInspectionItem item : patMedInspectionItems) { |
| | | if (StringUtils.isNotBlank(inspectionName) && inspectionName.equals(item.getInspectionName())) { |
| | | existingItem = item; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | if (existingItem == null) { |
| | | existingItem = patMedInspectionItems.get(0); |
| | | } |
| | | } |
| | | if (ObjectUtils.isNotEmpty(patMedInspectionItems)) { |
| | | |
| | | if (existingItem != null) { |
| | | // 更新必须带上主键,否则 update ... where id = null 会影响 0 行,接口返回失败 |
| | | patMedInspectionItem.setId(existingItem.getId()); |
| | | patMedInspectionItem.setUpdateTime(new Date()); |
| | | int i = patMedInspectionItemMapper.updatePatMedInspectionItem(patMedInspectionItem); |
| | | if (i != 1) return false; |
| | | if (i < 1) { |
| | | throw new BaseException("检查报告明细更新失败,id=" + existingItem.getId()); |
| | | } |
| | | } else { |
| | | patMedInspectionItem.setDelFlag("0"); |
| | | patMedInspectionItem.setCreateTime(new Date()); |
| | | int i = patMedInspectionItemMapper.insertPatMedInspectionItem(patMedInspectionItem); |
| | | if (i != 1) return false; |
| | | if (i != 1) { |
| | | throw new BaseException("检查报告明细新增失败,ShenQingDID=" + shenQingDID); |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 从报文中按顺序获取第一个非空字段,兼容不同厂商的字段命名 |
| | | */ |
| | | private String getMapValue(Map<String, Object> source, String... keys) { |
| | | if (source == null || keys == null) { |
| | | return null; |
| | | } |
| | | for (String key : keys) { |
| | | Object value = source.get(key); |
| | | if (value != null && StringUtils.isNotBlank(String.valueOf(value))) { |
| | | return String.valueOf(value); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 解析检查报告时间,兼容常见日期时间格式 |
| | | */ |
| | | private Date parseDateTime(String dateTime) { |
| | | if (StringUtils.isBlank(dateTime)) { |
| | | return null; |
| | | } |
| | | String[] patterns = {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd"}; |
| | | for (String pattern : patterns) { |
| | | try { |
| | | SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); |
| | | simpleDateFormat.setLenient(false); |
| | | return simpleDateFormat.parse(dateTime); |
| | | } catch (ParseException ignored) { |
| | | // 尝试下一种格式 |
| | | } |
| | | } |
| | | log.warn("检查报告时间格式无法解析:{}", dateTime); |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 解析检查报告数字字段,避免非数字内容导致接口报错 |
| | | */ |
| | | private Integer parseInteger(String value) { |
| | | if (StringUtils.isBlank(value)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return Integer.valueOf(value.trim()); |
| | | } catch (NumberFormatException e) { |
| | | log.warn("检查报告数字字段无法转换:{}", value); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | | * 完成接诊时按专科档案生成配置生成妇科/儿科档案。 |
| | | * |
| | | * <p>生成逻辑内部只对指定机构生效,未命中配置或生成失败均不影响接诊主流程。</p> |
| | | */ |
| | | private void genePatSpecificArchive(PatMedOuthosp patMedOuthosp, PatArchive patArchive) { |
| | | try { |
| | | int generated = patSpecificArchiveGenerateService.generateByOuthosp(patMedOuthosp, patArchive); |
| | | if (generated > 0) { |
| | | log.info("完成接诊自动生成专科档案成功,outhospno={},生成数量={}", |
| | | patMedOuthosp.getOuthospno(), generated); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("完成接诊自动生成专科档案失败,outhospno={}", patMedOuthosp.getOuthospno(), e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 判断当前科室属于妇科还是儿科 |
| | | * |
| | | * @param deptCode 当前科室/病区 Code,如 "D004" |
| | | * @param orgid 医院机构ID |
| | | * @return deptCategory:1-妇科 2-儿科;null-未配置或未命中 |
| | | */ |
| | | public String judgeDeptCategory(String deptCode, String orgid) { |
| | | if (StringUtils.isEmpty(deptCode)) { |
| | | return null; |
| | | } |
| | | |
| | | // 优先取机构级配置,取不到再取全局配置 |
| | | String configValue = configService.selectConfigByKey("sys.dept.category", |
| | | orgid); |
| | | if (StringUtils.isEmpty(configValue)) { |
| | | configValue = configService.selectConfigByKey("sys.dept.category"); |
| | | } |
| | | if (StringUtils.isEmpty(configValue)) { |
| | | return null; |
| | | } |
| | | |
| | | JSONArray configs = JSON.parseArray(configValue); |
| | | if (configs == null || configs.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | for (int i = 0; i < configs.size(); i++) { |
| | | JSONObject cfg = configs.getJSONObject(i); |
| | | JSONArray deptCodes = cfg.getJSONArray("deptCodes"); |
| | | if (deptCodes != null && deptCodes.contains(deptCode)) { |
| | | return cfg.getString("deptCategory"); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |