package com.smartor.service.impl;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.smartor.common.SpecificArchiveConstants;
|
import com.smartor.domain.PatArchive;
|
import com.smartor.domain.PatChildArchiveDetail;
|
import com.smartor.domain.PatMaternityArchiveDetail;
|
import com.smartor.domain.PatMedOuthosp;
|
import com.smartor.domain.PatSpecificArchiveGenerateConfig;
|
import com.smartor.mapper.PatArchiveMapper;
|
import com.smartor.service.IPatChildArchiveService;
|
import com.smartor.service.IPatMaternityArchiveService;
|
import com.smartor.service.IPatSpecificArchiveGenerateConfigService;
|
import com.smartor.service.IPatSpecificArchiveGenerateService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.collections4.CollectionUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
/**
|
* 专科档案生成Service业务层处理。
|
*
|
* <p>只处理丽水市妇幼保健院(orgid = 47226079133110211G1001)的门诊接诊完成记录,
|
* 按 {@code pat_specific_archive_generate_config} 配置匹配科室和诊断后,
|
* 生成对应类型的妇科档案或儿科档案。</p>
|
*/
|
@Slf4j
|
@Service
|
public class PatSpecificArchiveGenerateServiceImpl implements IPatSpecificArchiveGenerateService {
|
|
/** 部门分类:妇科 */
|
private static final String DEPT_CATEGORY_GYNECOLOGY = "1";
|
/** 部门分类:儿科 */
|
private static final String DEPT_CATEGORY_PEDIATRICS = "2";
|
/** 部门类型:科室 */
|
private static final String DEPT_TYPE_DEPARTMENT = "1";
|
/** 来源类型:门诊记录 */
|
private static final String SOURCE_TYPE_OUTHOSP = "1";
|
|
@Autowired
|
private IPatSpecificArchiveGenerateConfigService patSpecificArchiveGenerateConfigService;
|
|
@Autowired
|
private IPatMaternityArchiveService patMaternityArchiveService;
|
|
@Autowired
|
private IPatChildArchiveService patChildArchiveService;
|
|
@Autowired
|
private PatArchiveMapper patArchiveMapper;
|
|
@Override
|
public int generateByOuthosp(PatMedOuthosp patMedOuthosp, PatArchive patArchive) {
|
if (patMedOuthosp == null) {
|
return 0;
|
}
|
// 仅丽水市妇幼保健院生效,避免影响其他机构
|
if (!SpecificArchiveConstants.LISHUI_MCH_ORG_ID.equals(patMedOuthosp.getOrgid())) {
|
return 0;
|
}
|
if (StringUtils.isBlank(patMedOuthosp.getOuthospno())) {
|
log.warn("生成专科档案跳过:门诊编号为空,serialnum={}", patMedOuthosp.getSerialnum());
|
return 0;
|
}
|
|
PatArchive targetArchive = resolvePatArchive(patMedOuthosp, patArchive);
|
if (targetArchive == null && patMedOuthosp.getPatid() != null) {
|
targetArchive = patArchiveMapper.selectPatArchiveByPatid(patMedOuthosp.getPatid());
|
}
|
Long patid = targetArchive != null ? targetArchive.getId() : patMedOuthosp.getPatid();
|
if (patid == null) {
|
log.warn("生成专科档案跳过:未找到患者档案,outhospno={},patno={}",
|
patMedOuthosp.getOuthospno(), patMedOuthosp.getPatno());
|
return 0;
|
}
|
|
String campusid = StringUtils.isNotBlank(patMedOuthosp.getCampusid())
|
? patMedOuthosp.getCampusid() : "1";
|
List<PatSpecificArchiveGenerateConfig> configs =
|
patSpecificArchiveGenerateConfigService.selectEffectiveConfigList(patMedOuthosp.getOrgid(), campusid);
|
if (CollectionUtils.isEmpty(configs)) {
|
log.debug("生成专科档案跳过:机构未配置档案生成规则,orgid={},campusid={}",
|
patMedOuthosp.getOrgid(), campusid);
|
return 0;
|
}
|
|
// 同一条门诊记录、同一部门分类、同一档案类型只生成一次
|
Set<String> generatedKeys = new HashSet<>();
|
int generatedCount = 0;
|
for (PatSpecificArchiveGenerateConfig config : configs) {
|
if (!matchConfig(config, patMedOuthosp)) {
|
continue;
|
}
|
String archiveType = config.getArchiveType();
|
String deptCategory = config.getDeptCategory();
|
if (StringUtils.isBlank(archiveType) || StringUtils.isBlank(deptCategory)) {
|
log.warn("生成专科档案跳过:配置不完整,configId={},deptCategory={},archiveType={}",
|
config.getId(), deptCategory, archiveType);
|
continue;
|
}
|
|
String generatedKey = deptCategory + "|" + archiveType;
|
if (!generatedKeys.add(generatedKey)) {
|
continue;
|
}
|
|
try {
|
if (DEPT_CATEGORY_GYNECOLOGY.equals(deptCategory)) {
|
PatMaternityArchiveDetail detail =
|
buildMaternityDetail(patMedOuthosp, targetArchive, config, campusid);
|
patMaternityArchiveService.insertOrUpdateMaternityArchive(detail);
|
generatedCount++;
|
} else if (DEPT_CATEGORY_PEDIATRICS.equals(deptCategory)) {
|
PatChildArchiveDetail detail =
|
buildChildDetail(patMedOuthosp, targetArchive, config, campusid);
|
patChildArchiveService.insertOrUpdateChildArchive(detail);
|
generatedCount++;
|
} else {
|
log.warn("生成专科档案跳过:未知部门分类,configId={},deptCategory={}",
|
config.getId(), deptCategory);
|
}
|
} catch (Exception e) {
|
log.error("生成专科档案失败,configId={},outhospno={},deptCategory={},archiveType={}",
|
config.getId(), patMedOuthosp.getOuthospno(), deptCategory, archiveType, e);
|
}
|
}
|
return generatedCount;
|
}
|
|
/**
|
* 判断门诊记录是否命中配置。
|
*
|
* <p>部门条件与诊断条件为 OR 关系:任一条件命中即生成;两个集合都为空时配置无效。</p>
|
*/
|
private boolean matchConfig(PatSpecificArchiveGenerateConfig config, PatMedOuthosp patMedOuthosp) {
|
List<String> deptCodes = parseCodes(config.getDeptCodes());
|
List<String> icd10Codes = parseCodes(config.getIcd10Codes());
|
if (CollectionUtils.isEmpty(deptCodes) && CollectionUtils.isEmpty(icd10Codes)) {
|
return false;
|
}
|
|
boolean deptMatched = false;
|
if (CollectionUtils.isNotEmpty(deptCodes)) {
|
// 门诊记录只有科室,没有病区;dept_type=2(病区)不参与门诊匹配
|
if (DEPT_TYPE_DEPARTMENT.equals(config.getDeptType())) {
|
deptMatched = containsIgnoreCase(deptCodes, patMedOuthosp.getDeptcode());
|
}
|
}
|
|
boolean diagnosisMatched = false;
|
if (CollectionUtils.isNotEmpty(icd10Codes)) {
|
String icd10code = patMedOuthosp.getIcd10code();
|
String diagname = patMedOuthosp.getDiagname();
|
diagnosisMatched = icd10Codes.stream().anyMatch(code -> {
|
if (equalsIgnoreCase(code, icd10code)) {
|
return true;
|
}
|
// 部分 HIS 数据只有诊断名称没有诊断码,此时允许按诊断名称兜底匹配
|
return StringUtils.isBlank(icd10code) && equalsIgnoreCase(code, diagname);
|
});
|
}
|
|
return deptMatched || diagnosisMatched;
|
}
|
|
private PatMaternityArchiveDetail buildMaternityDetail(PatMedOuthosp patMedOuthosp, PatArchive patArchive,
|
PatSpecificArchiveGenerateConfig config, String campusid) {
|
PatMaternityArchiveDetail detail = new PatMaternityArchiveDetail();
|
detail.setArchiveType(config.getArchiveType());
|
detail.setFollowupPeriod(config.getFollowupPeriod());
|
detail.setSourceType(SOURCE_TYPE_OUTHOSP);
|
fillCommonDetail(detail, patMedOuthosp, patArchive, campusid);
|
if (patArchive != null) {
|
detail.setAddress(patArchive.getPlaceOfResidence());
|
}
|
return detail;
|
}
|
|
private PatChildArchiveDetail buildChildDetail(PatMedOuthosp patMedOuthosp, PatArchive patArchive,
|
PatSpecificArchiveGenerateConfig config, String campusid) {
|
PatChildArchiveDetail detail = new PatChildArchiveDetail();
|
detail.setArchiveType(config.getArchiveType());
|
detail.setFollowupPeriod(config.getFollowupPeriod());
|
detail.setSourceType(SOURCE_TYPE_OUTHOSP);
|
fillCommonChildDetail(detail, patMedOuthosp, patArchive, campusid);
|
detail.setParentPhone(patArchive != null
|
? firstNotBlank(patArchive.getTelcode(), patMedOuthosp.getTelcode())
|
: patMedOuthosp.getTelcode());
|
if (patArchive != null) {
|
detail.setParentAddress(patArchive.getPlaceOfResidence());
|
}
|
// 营养性疾病档案同步诊断信息,方便列表直接展示
|
if ("1".equals(config.getArchiveType())) {
|
detail.setNutritionIcd10Code(patMedOuthosp.getIcd10code());
|
detail.setNutritionDiagName(patMedOuthosp.getDiagname());
|
}
|
return detail;
|
}
|
|
private void fillCommonDetail(PatMaternityArchiveDetail detail, PatMedOuthosp patMedOuthosp,
|
PatArchive patArchive, String campusid) {
|
detail.setOuthospno(patMedOuthosp.getOuthospno());
|
detail.setSerialnum(patMedOuthosp.getSerialnum());
|
detail.setPatid(patArchive != null ? patArchive.getId() : patMedOuthosp.getPatid());
|
detail.setPatname(patArchive != null
|
? firstNotBlank(patArchive.getName(), patMedOuthosp.getPatname()) : patMedOuthosp.getPatname());
|
detail.setBirthdate(patArchive != null ? patArchive.getBirthdate() : null);
|
detail.setIdcardno(patArchive != null
|
? firstNotBlank(patArchive.getIdcardno(), patMedOuthosp.getIdcardno()) : patMedOuthosp.getIdcardno());
|
detail.setPhone(patArchive != null
|
? firstNotBlank(patArchive.getTelcode(), patMedOuthosp.getTelcode()) : patMedOuthosp.getTelcode());
|
detail.setSex(patArchive != null && patArchive.getSex() != null
|
? patArchive.getSex() : patMedOuthosp.getSex());
|
detail.setDiagTime(patMedOuthosp.getAdmitdate());
|
detail.setArchiveTime(new Date());
|
detail.setDoctorCode(patMedOuthosp.getDrcode());
|
detail.setDoctorName(patMedOuthosp.getDrname());
|
detail.setManagementDoctorCode(patMedOuthosp.getDrcode());
|
detail.setManagementDoctorName(patMedOuthosp.getDrname());
|
detail.setFirstDoctorCode(patMedOuthosp.getDrcode());
|
detail.setFirstDoctorName(patMedOuthosp.getDrname());
|
detail.setDeptcode(patMedOuthosp.getDeptcode());
|
detail.setDeptname(patMedOuthosp.getDeptname());
|
detail.setIcd10code(patMedOuthosp.getIcd10code());
|
detail.setDiagname(patMedOuthosp.getDiagname());
|
detail.setRegisterUser(patMedOuthosp.getDrname());
|
detail.setOrgid(patMedOuthosp.getOrgid());
|
detail.setCampusid(campusid);
|
detail.setDelFlag("0");
|
}
|
|
private void fillCommonChildDetail(PatChildArchiveDetail detail, PatMedOuthosp patMedOuthosp,
|
PatArchive patArchive, String campusid) {
|
detail.setOuthospno(patMedOuthosp.getOuthospno());
|
detail.setSerialnum(patMedOuthosp.getSerialnum());
|
detail.setPatid(patArchive != null ? patArchive.getId() : patMedOuthosp.getPatid());
|
detail.setPatname(patArchive != null
|
? firstNotBlank(patArchive.getName(), patMedOuthosp.getPatname()) : patMedOuthosp.getPatname());
|
detail.setBirthdate(patArchive != null ? patArchive.getBirthdate() : null);
|
detail.setIdcardno(patArchive != null
|
? firstNotBlank(patArchive.getIdcardno(), patMedOuthosp.getIdcardno()) : patMedOuthosp.getIdcardno());
|
detail.setPhone(patArchive != null
|
? firstNotBlank(patArchive.getTelcode(), patMedOuthosp.getTelcode()) : patMedOuthosp.getTelcode());
|
detail.setSex(patArchive != null && patArchive.getSex() != null
|
? patArchive.getSex() : patMedOuthosp.getSex());
|
detail.setDiagTime(patMedOuthosp.getAdmitdate());
|
detail.setArchiveTime(new Date());
|
detail.setDoctorCode(patMedOuthosp.getDrcode());
|
detail.setDoctorName(patMedOuthosp.getDrname());
|
detail.setManagementDoctorCode(patMedOuthosp.getDrcode());
|
detail.setManagementDoctorName(patMedOuthosp.getDrname());
|
detail.setDeptcode(patMedOuthosp.getDeptcode());
|
detail.setDeptname(patMedOuthosp.getDeptname());
|
detail.setIcd10code(patMedOuthosp.getIcd10code());
|
detail.setDiagname(patMedOuthosp.getDiagname());
|
detail.setRegisterUser(patMedOuthosp.getDrname());
|
detail.setOrgid(patMedOuthosp.getOrgid());
|
detail.setCampusid(campusid);
|
detail.setDelFlag("0");
|
}
|
|
private PatArchive resolvePatArchive(PatMedOuthosp patMedOuthosp, PatArchive patArchive) {
|
if (patArchive != null && patArchive.getId() != null) {
|
return patArchive;
|
}
|
|
PatArchive query = new PatArchive();
|
if (StringUtils.isNotBlank(patMedOuthosp.getPatno())) {
|
query.setPatientno(patMedOuthosp.getPatno());
|
} else if (StringUtils.isNotBlank(patMedOuthosp.getIdcardno())) {
|
query.setIdcardno(patMedOuthosp.getIdcardno());
|
} else {
|
return null;
|
}
|
query.setOrgid(patMedOuthosp.getOrgid());
|
|
List<PatArchive> archives = patArchiveMapper.selectPatArchiveList(query);
|
return CollectionUtils.isNotEmpty(archives) ? archives.get(0) : null;
|
}
|
|
private List<String> parseCodes(String raw) {
|
if (StringUtils.isBlank(raw)) {
|
return Collections.emptyList();
|
}
|
String value = raw.trim();
|
try {
|
JSONArray array = JSON.parseArray(value);
|
if (array != null) {
|
List<String> result = new ArrayList<>();
|
for (Object item : array) {
|
if (item != null && StringUtils.isNotBlank(String.valueOf(item))) {
|
result.add(String.valueOf(item).trim());
|
}
|
}
|
return result;
|
}
|
} catch (Exception e) {
|
log.warn("解析档案生成配置集合失败,按逗号分隔处理:{}", raw);
|
}
|
return Arrays.stream(value.split(","))
|
.map(String::trim)
|
.filter(StringUtils::isNotBlank)
|
.collect(Collectors.toList());
|
}
|
|
private String firstNotBlank(String first, String second) {
|
return StringUtils.isNotBlank(first) ? first : second;
|
}
|
|
private boolean containsIgnoreCase(List<String> source, String target) {
|
if (StringUtils.isBlank(target)) {
|
return false;
|
}
|
return source.stream().anyMatch(item -> equalsIgnoreCase(item, target));
|
}
|
|
private boolean equalsIgnoreCase(String first, String second) {
|
return first != null && second != null && first.trim().equalsIgnoreCase(second.trim());
|
}
|
}
|