From 3d047130b059efd46f56be37465a751ab16ee8cb Mon Sep 17 00:00:00 2001
From: 陈昶聿 <chychen@nbjetron.com>
Date: 星期三, 11 十一月 2026 14:06:56 +0800
Subject: [PATCH] Merge branch 'smartor_ls_merge' into 20261111-妇幼档案随访

---
 smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateServiceImpl.java |  603 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 578 insertions(+), 25 deletions(-)

diff --git a/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateServiceImpl.java
index 91effdb..ee787a2 100644
--- a/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateServiceImpl.java
+++ b/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateServiceImpl.java
@@ -3,20 +3,31 @@
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.ruoyi.common.core.domain.entity.PatArchive;
+import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.inhospvisit.api.InhospVisitFacade;
+import com.ruoyi.inhospvisit.domain.PatMedInhosp;
 import com.ruoyi.outpatientvisit.domain.PatMedOuthosp;
 import com.ruoyi.patarchive.domain.PatSpecificArchiveGenerateConfig;
 import com.ruoyi.patarchive.mapper.PatArchiveMapper;
 import com.ruoyi.patarchive.service.IPatSpecificArchiveGenerateConfigService;
+import com.ruoyi.task.api.TaskSubtaskApi;
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.ruoyi.task.service.IServiceSubtaskService;
 import com.smartor.common.SpecificArchiveConstants;
+import com.smartor.domain.PatChildArchive;
 import com.smartor.domain.PatChildArchiveDetail;
+import com.smartor.domain.PatMaternityArchive;
 import com.smartor.domain.PatMaternityArchiveDetail;
+import com.smartor.domain.PatSpecificArchiveGenerateLog;
 import com.smartor.service.IPatChildArchiveService;
 import com.smartor.service.IPatMaternityArchiveService;
+import com.smartor.service.IPatSpecificArchiveGenerateLogService;
 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.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -26,27 +37,37 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
  * 涓撶妗f鐢熸垚Service涓氬姟灞傚鐞嗐��
  *
- * <p>鍙鐞嗕附姘村競濡囧辜淇濆仴闄紙orgid = 47226079133110211G1001锛夌殑闂ㄨ瘖鎺ヨ瘖瀹屾垚璁板綍锛�
- * 鎸� {@code pat_specific_archive_generate_config} 閰嶇疆鍖归厤绉戝鍜岃瘖鏂悗锛�
- * 鐢熸垚瀵瑰簲绫诲瀷鐨勫绉戞。妗堟垨鍎跨妗f銆�</p>
+ * <p>鍙鐞嗕附姘村競濡囧辜淇濆仴闄紙orgid = 47226079133110211G1001锛夛細</p>
+ * <ul>
+ *     <li>闂ㄨ瘖鎺ヨ瘖瀹屾垚锛氭寜绉戝/璇婃柇鍖归厤閰嶇疆鍚庣敓鎴愬绉�/鍎跨妗f锛�</li>
+ *     <li>浣忛櫌闅忚瀹屾垚锛氭寜鍑洪櫌/鍦ㄩ櫌绉戝銆佺梾鍖恒�佽瘖鏂尮閰嶉厤缃悗鐢熸垚濡囩/鍎跨妗f锛�
+ *     鐢熸垚鍓嶆寜鈥滄偅鑰� + 涓撶 + 妗f绫诲瀷鈥濆垽鏂槸鍚﹀凡鏈夊搴旀。妗堬紝宸叉湁鍒欒烦杩囥��</li>
+ * </ul>
  */
 @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";
+    /** 閮ㄩ棬绫诲瀷锛氱梾鍖� */
+    private static final String DEPT_TYPE_WARD = "2";
+    /** 灏辫瘖绫诲瀷锛氬嚭闄� */
+    private static final String HOSP_TYPE_DISCHARGE = "2";
+    /** 灏辫瘖绫诲瀷锛氫綇闄�/鍏ラ櫌 */
+    private static final String HOSP_TYPE_INHOSP = "6";
+    /** 浣忛櫌闅忚瀹屾垚鐘舵�� */
+    private static final Long SEND_STATE_FINISHED = 6L;
+    /** 浣忛櫌闅忚妗f鐢熸垚鐨勬渶澶ч噸璇曟鏁� */
+    private static final int MAX_RETRY = 3;
+    /** Redis 閿佸墠缂� */
+    private static final String LOCK_PREFIX = "lock:archive:inhosp:";
 
     @Autowired
     private IPatSpecificArchiveGenerateConfigService patSpecificArchiveGenerateConfigService;
@@ -58,7 +79,32 @@
     private IPatChildArchiveService patChildArchiveService;
 
     @Autowired
+    private IPatSpecificArchiveGenerateLogService patSpecificArchiveGenerateLogService;
+
+    @Autowired
     private PatArchiveMapper patArchiveMapper;
+
+    @Autowired
+    private IServiceSubtaskService serviceSubtaskService;
+
+    @Autowired
+    private InhospVisitFacade inhospVisitFacade;
+
+    @Autowired
+    private TaskSubtaskApi taskSubtaskApi;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 浣忛櫌闅忚鏈嶅姟绫诲瀷鐧藉悕鍗曪紝榛樿鍑洪櫌闅忚銆佷笓绉戦殢璁裤�佸叆闄㈤殢璁裤�佹墜鏈殢璁裤��
+     */
+    @Value("${archive.inhosp.followup.service-types:2,13,18,19}")
+    private String inhospFollowupServiceTypes;
+
+    /** 浣忛櫌闅忚鐢熸垚涓撶妗f寮�鍏筹紝榛樿寮�鍚紝渚夸簬鎸夋満鏋勭伆搴︺�� */
+    @Value("${archive.inhosp.followup.enabled:true}")
+    private boolean inhospFollowupEnabled;
 
     @Override
     public int generateByOuthosp(PatMedOuthosp patMedOuthosp, PatArchive patArchive) {
@@ -86,7 +132,7 @@
         }
 
         String campusid = StringUtils.isNotBlank(patMedOuthosp.getCampusid())
-                ? patMedOuthosp.getCampusid() : "1";
+                ? patMedOuthosp.getCampusid() : SpecificArchiveConstants.DEFAULT_CAMPUS_ID;
         List<PatSpecificArchiveGenerateConfig> configs =
                 patSpecificArchiveGenerateConfigService.selectEffectiveConfigList(patMedOuthosp.getOrgid(), campusid);
         if (CollectionUtils.isEmpty(configs)) {
@@ -99,7 +145,8 @@
         Set<String> generatedKeys = new HashSet<>();
         int generatedCount = 0;
         for (PatSpecificArchiveGenerateConfig config : configs) {
-            if (!matchConfig(config, patMedOuthosp)) {
+            if (!matchConfig(config, patMedOuthosp.getDeptcode(), null,
+                    patMedOuthosp.getIcd10code(), patMedOuthosp.getDiagname())) {
                 continue;
             }
             String archiveType = config.getArchiveType();
@@ -116,12 +163,12 @@
             }
 
             try {
-                if (DEPT_CATEGORY_GYNECOLOGY.equals(deptCategory)) {
+                if (SpecificArchiveConstants.DEPT_CATEGORY_GYNECOLOGY.equals(deptCategory)) {
                     PatMaternityArchiveDetail detail =
                             buildMaternityDetail(patMedOuthosp, targetArchive, config, campusid);
                     patMaternityArchiveService.insertOrUpdateMaternityArchive(detail);
                     generatedCount++;
-                } else if (DEPT_CATEGORY_PEDIATRICS.equals(deptCategory)) {
+                } else if (SpecificArchiveConstants.DEPT_CATEGORY_PEDIATRICS.equals(deptCategory)) {
                     PatChildArchiveDetail detail =
                             buildChildDetail(patMedOuthosp, targetArchive, config, campusid);
                     patChildArchiveService.insertOrUpdateChildArchive(detail);
@@ -138,12 +185,276 @@
         return generatedCount;
     }
 
+    @Override
+    public int generateByInhospFollowup(Long subId) {
+        if (!inhospFollowupEnabled || subId == null) {
+            return 0;
+        }
+        ServiceSubtask subtask = serviceSubtaskService.selectServiceSubtaskById(subId);
+        if (subtask == null || !SEND_STATE_FINISHED.equals(subtask.getSendstate())) {
+            return 0;
+        }
+        if (!isInhospFollowup(subtask)) {
+            return 0;
+        }
+
+        // 浠呴檺涓芥按濡囧辜锛屾満鏋勪负绌烘椂鐢ㄤ綇闄㈣褰�/鎮h�呮。妗堝厹搴�
+        PatMedInhosp inhosp = resolveInhosp(subtask);
+        PatArchive patArchive = resolvePatArchive(subtask.getPatid(), inhosp);
+        String orgid = firstNotBlank(subtask.getOrgid(),
+                inhosp == null ? null : inhosp.getOrgid(),
+                patArchive == null ? null : patArchive.getOrgid());
+        if (!SpecificArchiveConstants.LISHUI_MCH_ORG_ID.equals(orgid)) {
+            log.debug("浣忛櫌闅忚鐢熸垚涓撶妗f璺宠繃锛氶潪涓芥按濡囧辜鏈烘瀯锛宻ubId={}锛宱rgid={}", subId, orgid);
+            return 0;
+        }
+
+        Long patid = firstNonNull(subtask.getPatid(),
+                inhosp == null ? null : inhosp.getPatid(),
+                patArchive == null ? null : patArchive.getId());
+        if (patid == null) {
+            log.warn("浣忛櫌闅忚鐢熸垚涓撶妗f璺宠繃锛氭湭鎵惧埌鎮h�咃紝subId={}锛宨nhospid={}", subId, subtask.getInhospid());
+            return 0;
+        }
+        if (patArchive == null) {
+            patArchive = patArchiveMapper.selectPatArchiveByPatid(patid);
+        }
+
+        String campusid = firstNotBlank(subtask.getCampusid(),
+                inhosp == null ? null : inhosp.getCampusid(),
+                patArchive == null ? null : patArchive.getCampusid(),
+                SpecificArchiveConstants.DEFAULT_CAMPUS_ID);
+
+        boolean admission = HOSP_TYPE_INHOSP.equals(subtask.getHospType());
+        String deptCode = admission
+                ? firstNotBlank(inhosp == null ? null : inhosp.getDeptcode(), subtask.getDeptcode(),
+                subtask.getVisitDeptCode(), subtask.getLeaveldeptcode())
+                : firstNotBlank(inhosp == null ? null : inhosp.getLeaveldeptcode(), subtask.getLeaveldeptcode(),
+                subtask.getVisitDeptCode(), inhosp == null ? null : inhosp.getDeptcode());
+        String deptName = admission
+                ? firstNotBlank(inhosp == null ? null : inhosp.getDeptname(), subtask.getDeptname(),
+                subtask.getVisitDeptName(), subtask.getLeaveldeptname())
+                : firstNotBlank(inhosp == null ? null : inhosp.getLeaveldeptname(), subtask.getLeaveldeptname(),
+                subtask.getVisitDeptName(), inhosp == null ? null : inhosp.getDeptname());
+        String wardCode = admission
+                ? firstNotBlank(inhosp == null ? null : inhosp.getHospitaldistrictcode(),
+                subtask.getHospitaldistrictcode(), subtask.getLeavehospitaldistrictcode())
+                : firstNotBlank(inhosp == null ? null : inhosp.getLeavehospitaldistrictcode(),
+                subtask.getLeavehospitaldistrictcode(), subtask.getHospitaldistrictcode());
+        String wardName = admission
+                ? firstNotBlank(inhosp == null ? null : inhosp.getHospitaldistrictname(),
+                subtask.getHospitaldistrictname(), subtask.getLeavehospitaldistrictname())
+                : firstNotBlank(inhosp == null ? null : inhosp.getLeavehospitaldistrictname(),
+                subtask.getLeavehospitaldistrictname(), subtask.getHospitaldistrictname());
+        String icd10Code = admission
+                ? firstNotBlank(inhosp == null ? null : inhosp.getIcd10code(), subtask.getLeaveicd10code())
+                : firstNotBlank(inhosp == null ? null : inhosp.getLeaveicd10code(),
+                subtask.getLeaveicd10code(), inhosp == null ? null : inhosp.getIcd10code());
+        String diagName = admission
+                ? firstNotBlank(inhosp == null ? null : inhosp.getDiagname(), subtask.getDiagname())
+                : firstNotBlank(inhosp == null ? null : inhosp.getLeavediagname(),
+                subtask.getLeavediagname(), inhosp == null ? null : inhosp.getDiagname());
+
+        InhospArchiveContext context = new InhospArchiveContext();
+        context.subtask = subtask;
+        context.inhosp = inhosp;
+        context.patArchive = patArchive;
+        context.patid = patid;
+        context.orgid = orgid;
+        context.campusid = campusid;
+        context.deptCode = deptCode;
+        context.deptName = deptName;
+        context.wardCode = wardCode;
+        context.wardName = wardName;
+        context.icd10Code = icd10Code;
+        context.diagName = diagName;
+        context.diagTime = firstDate(subtask.getFinishtime(), inhosp == null ? null : inhosp.getEndtime());
+
+        List<PatSpecificArchiveGenerateConfig> configs =
+                patSpecificArchiveGenerateConfigService.selectEffectiveConfigList(orgid, campusid);
+        if (CollectionUtils.isEmpty(configs)) {
+            recordLog(context, null, null, null, SpecificArchiveConstants.RESULT_NO_MATCH, null,
+                    "鏈烘瀯鏈厤缃。妗堢敓鎴愯鍒�");
+            return 0;
+        }
+
+        Set<String> generatedKeys = new HashSet<>();
+        int generatedCount = 0;
+        boolean anyMatched = false;
+        for (PatSpecificArchiveGenerateConfig config : configs) {
+            String archiveType = config.getArchiveType();
+            String deptCategory = config.getDeptCategory();
+            if (StringUtils.isBlank(archiveType) || StringUtils.isBlank(deptCategory)) {
+                log.warn("浣忛櫌闅忚鐢熸垚涓撶妗f璺宠繃锛氶厤缃笉瀹屾暣锛宑onfigId={}锛宒eptCategory={}锛宎rchiveType={}",
+                        config.getId(), deptCategory, archiveType);
+                continue;
+            }
+            if (!matchConfig(config, deptCode, wardCode, icd10Code, diagName)) {
+                continue;
+            }
+            anyMatched = true;
+            String generatedKey = deptCategory + "|" + archiveType;
+            if (!generatedKeys.add(generatedKey)) {
+                continue;
+            }
+            if (alreadyProcessed(subId, config.getId())) {
+                continue;
+            }
+
+            String lockKey = LOCK_PREFIX + orgid + ":" + patid + ":" + deptCategory + ":" + archiveType;
+            boolean locked = false;
+            try {
+                locked = redisCache.setCacheObjectIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);
+            } catch (Exception e) {
+                // Redis 涓嶅彲鐢ㄦ椂 fail-open锛屼緷璧栫敓鎴愭棩蹇楀拰鏁版嵁搴撴煡璇㈠厹搴曪紝閬垮厤妗f鐢熸垚鏁翠綋鍋滄憜
+                locked = true;
+                log.warn("浣忛櫌闅忚鐢熸垚涓撶妗f鑾峰彇Redis閿佸紓甯革紝闄嶇骇涓烘棤閿佹墽琛岋紝subId={}锛宭ockKey={}", subId, lockKey, e);
+            }
+            if (!locked) {
+                // 鏈嬁鍒伴攣鏃剁敱琛ュ伩浠诲姟閲嶈瘯锛岄伩鍏嶅苟鍙戦噸澶嶇敓鎴�
+                log.info("浣忛櫌闅忚鐢熸垚涓撶妗f鏈幏鍙栧埌閿侊紝绛夊緟琛ュ伩閲嶈瘯锛宻ubId={}锛宭ockKey={}", subId, lockKey);
+                recordLog(context, config, deptCategory, archiveType, SpecificArchiveConstants.RESULT_FAILED,
+                        null, "鑾峰彇鐢熸垚閿佸け璐�");
+                continue;
+            }
+
+            try {
+                Long existingArchiveId = findExistingArchiveId(orgid, patid, deptCategory, archiveType);
+                if (existingArchiveId != null) {
+                    recordLog(context, config, deptCategory, archiveType,
+                            SpecificArchiveConstants.RESULT_EXISTS, existingArchiveId, "鎮h�呭凡鏈夊搴旀。妗堬紝璺宠繃鐢熸垚");
+                    continue;
+                }
+
+                Long archiveId;
+                if (SpecificArchiveConstants.DEPT_CATEGORY_GYNECOLOGY.equals(deptCategory)) {
+                    PatMaternityArchiveDetail detail = buildInhospMaternityDetail(context, config);
+                    archiveId = (long) patMaternityArchiveService.insertOrUpdateMaternityArchive(detail);
+                } else if (SpecificArchiveConstants.DEPT_CATEGORY_PEDIATRICS.equals(deptCategory)) {
+                    PatChildArchiveDetail detail = buildInhospChildDetail(context, config);
+                    archiveId = (long) patChildArchiveService.insertOrUpdateChildArchive(detail);
+                } else {
+                    log.warn("浣忛櫌闅忚鐢熸垚涓撶妗f璺宠繃锛氭湭鐭ラ儴闂ㄥ垎绫伙紝configId={}锛宒eptCategory={}",
+                            config.getId(), deptCategory);
+                    continue;
+                }
+                recordLog(context, config, deptCategory, archiveType,
+                        SpecificArchiveConstants.RESULT_GENERATED, archiveId, "鐢熸垚鎴愬姛");
+                generatedCount++;
+            } catch (Exception e) {
+                log.error("浣忛櫌闅忚鐢熸垚涓撶妗f澶辫触锛宻ubId={}锛宑onfigId={}锛宒eptCategory={}锛宎rchiveType={}",
+                        subId, config.getId(), deptCategory, archiveType, e);
+                recordLog(context, config, deptCategory, archiveType,
+                        SpecificArchiveConstants.RESULT_FAILED, null, truncateMsg(e.getMessage()));
+            } finally {
+                if (locked) {
+                    try {
+                        redisCache.deleteObject(lockKey);
+                    } catch (Exception e) {
+                        log.warn("浣忛櫌闅忚鐢熸垚涓撶妗f閲婃斁Redis閿佸紓甯革紝lockKey={}", lockKey, e);
+                    }
+                }
+            }
+        }
+
+        if (!anyMatched) {
+            recordLog(context, null, null, null, SpecificArchiveConstants.RESULT_NO_MATCH, null,
+                    "鏈懡涓瀹�/鐥呭尯/璇婃柇閰嶇疆");
+        }
+        return generatedCount;
+    }
+
+    @Override
+    public int compensateInhospFollowups() {
+        if (!inhospFollowupEnabled) {
+            return 0;
+        }
+        List<String> serviceTypes = parseCsv(inhospFollowupServiceTypes);
+        if (CollectionUtils.isEmpty(serviceTypes)) {
+            return 0;
+        }
+        Date startTime = new Date(System.currentTimeMillis() - 7L * 24 * 60 * 60 * 1000);
+        List<ServiceSubtask> subtasks = taskSubtaskApi.findCompletedInhospFollowups(
+                SpecificArchiveConstants.LISHUI_MCH_ORG_ID, serviceTypes, startTime, 200);
+        if (CollectionUtils.isEmpty(subtasks)) {
+            return 0;
+        }
+        int generated = 0;
+        for (ServiceSubtask subtask : subtasks) {
+            if (subtask.getId() == null
+                    || patSpecificArchiveGenerateLogService.existsProcessedBySourceSub(
+                    SpecificArchiveConstants.SOURCE_TYPE_INHOSP_FOLLOWUP, subtask.getId())) {
+                continue;
+            }
+            try {
+                generated += generateByInhospFollowup(subtask.getId());
+            } catch (Exception e) {
+                log.error("琛ュ伩鐢熸垚浣忛櫌闅忚涓撶妗f澶辫触锛宻ubId={}", subtask.getId(), e);
+            }
+        }
+        return generated;
+    }
+
     /**
-     * 鍒ゆ柇闂ㄨ瘖璁板綍鏄惁鍛戒腑閰嶇疆銆�
+     * 鍒ゆ柇闅忚瀛愪换鍔℃槸鍚﹀睘浜庨渶瑕佺敓鎴愭。妗堢殑浣忛櫌闅忚銆�
+     */
+    private boolean isInhospFollowup(ServiceSubtask subtask) {
+        if (!HOSP_TYPE_DISCHARGE.equals(subtask.getHospType())
+                && !HOSP_TYPE_INHOSP.equals(subtask.getHospType())) {
+            return false;
+        }
+        if (StringUtils.isBlank(subtask.getServiceType())) {
+            return false;
+        }
+        return parseCsv(inhospFollowupServiceTypes).contains(subtask.getServiceType().trim());
+    }
+
+    private boolean alreadyProcessed(Long subId, Long configId) {
+        int cid = configId == null ? SpecificArchiveConstants.NO_CONFIG_ID : configId.intValue();
+        PatSpecificArchiveGenerateLog old = patSpecificArchiveGenerateLogService
+                .selectBySourceSubAndConfig(SpecificArchiveConstants.SOURCE_TYPE_INHOSP_FOLLOWUP, subId, cid);
+        if (old == null) {
+            return false;
+        }
+        if (SpecificArchiveConstants.RESULT_FAILED.equals(old.getProcessResult())) {
+            return old.getRetryCount() != null && old.getRetryCount() >= MAX_RETRY;
+        }
+        return true;
+    }
+
+    /**
+     * 鏌ヨ鎮h�呮槸鍚﹀凡鏈夊搴斾笓绉戞。妗堛��
+     *
+     * <p>鐢ㄦ埛纭鍙e緞锛氭寜鈥滀笓绉� + 妗f绫诲瀷鈥濆垽鏂�傚绉戙�佸効绉戝垎琛ㄥ瓨鍌紝鍥犳濡囩鏌ュ绉戣〃锛�
+     * 鍎跨鏌ュ効绉戣〃锛屽啀鎸夋。妗堢被鍨嬪尯鍒嗐��</p>
+     */
+    private Long findExistingArchiveId(String orgid, Long patid, String deptCategory, String archiveType) {
+        if (SpecificArchiveConstants.DEPT_CATEGORY_GYNECOLOGY.equals(deptCategory)) {
+            PatMaternityArchive query = new PatMaternityArchive();
+            query.setOrgid(orgid);
+            query.setPatid(patid);
+            query.setArchiveType(archiveType);
+            List<PatMaternityArchive> list = patMaternityArchiveService.selectPatMaternityArchiveList(query);
+            return CollectionUtils.isNotEmpty(list) ? list.get(0).getId() : null;
+        }
+        if (SpecificArchiveConstants.DEPT_CATEGORY_PEDIATRICS.equals(deptCategory)) {
+            PatChildArchive query = new PatChildArchive();
+            query.setOrgid(orgid);
+            query.setPatid(patid);
+            query.setArchiveType(archiveType);
+            List<PatChildArchive> list = patChildArchiveService.selectPatChildArchiveList(query);
+            return CollectionUtils.isNotEmpty(list) ? list.get(0).getId() : null;
+        }
+        return null;
+    }
+
+    /**
+     * 鍒ゆ柇绉戝/鐥呭尯銆佽瘖鏂槸鍚﹀懡涓厤缃��
      *
      * <p>閮ㄩ棬鏉′欢涓庤瘖鏂潯浠朵负 OR 鍏崇郴锛氫换涓�鏉′欢鍛戒腑鍗崇敓鎴愶紱涓や釜闆嗗悎閮戒负绌烘椂閰嶇疆鏃犳晥銆�</p>
      */
-    private boolean matchConfig(PatSpecificArchiveGenerateConfig config, PatMedOuthosp patMedOuthosp) {
+    private boolean matchConfig(PatSpecificArchiveGenerateConfig config, String deptCode, String wardCode,
+                                String icd10Code, String diagName) {
         List<String> deptCodes = parseCodes(config.getDeptCodes());
         List<String> icd10Codes = parseCodes(config.getIcd10Codes());
         if (CollectionUtils.isEmpty(deptCodes) && CollectionUtils.isEmpty(icd10Codes)) {
@@ -152,22 +463,21 @@
 
         boolean deptMatched = false;
         if (CollectionUtils.isNotEmpty(deptCodes)) {
-            // 闂ㄨ瘖璁板綍鍙湁绉戝锛屾病鏈夌梾鍖猴紱dept_type=2锛堢梾鍖猴級涓嶅弬涓庨棬璇婂尮閰�
             if (DEPT_TYPE_DEPARTMENT.equals(config.getDeptType())) {
-                deptMatched = containsIgnoreCase(deptCodes, patMedOuthosp.getDeptcode());
+                deptMatched = containsIgnoreCase(deptCodes, deptCode);
+            } else if (DEPT_TYPE_WARD.equals(config.getDeptType())) {
+                deptMatched = containsIgnoreCase(deptCodes, wardCode);
             }
         }
 
         boolean diagnosisMatched = false;
         if (CollectionUtils.isNotEmpty(icd10Codes)) {
-            String icd10code = patMedOuthosp.getIcd10code();
-            String diagname = patMedOuthosp.getDiagname();
             diagnosisMatched = icd10Codes.stream().anyMatch(code -> {
-                if (equalsIgnoreCase(code, icd10code)) {
+                if (equalsIgnoreCase(code, icd10Code)) {
                     return true;
                 }
                 // 閮ㄥ垎 HIS 鏁版嵁鍙湁璇婃柇鍚嶇О娌℃湁璇婃柇鐮侊紝姝ゆ椂鍏佽鎸夎瘖鏂悕绉板厹搴曞尮閰�
-                return StringUtils.isBlank(icd10code) && equalsIgnoreCase(code, diagname);
+                return StringUtils.isBlank(icd10Code) && equalsIgnoreCase(code, diagName);
             });
         }
 
@@ -178,7 +488,10 @@
                                                            PatSpecificArchiveGenerateConfig config, String campusid) {
         PatMaternityArchiveDetail detail = new PatMaternityArchiveDetail();
         detail.setArchiveType(config.getArchiveType());
-        detail.setSourceType(SOURCE_TYPE_OUTHOSP);
+        detail.setFollowupPeriod(config.getFollowupPeriod());
+        detail.setSourceType(SpecificArchiveConstants.SOURCE_TYPE_OUTHOSP);
+        detail.setSourceBizId(patMedOuthosp.getId());
+        detail.setSourceBizNo(patMedOuthosp.getOuthospno());
         fillCommonDetail(detail, patMedOuthosp, patArchive, campusid);
         if (patArchive != null) {
             detail.setAddress(patArchive.getPlaceOfResidence());
@@ -190,7 +503,10 @@
                                                    PatSpecificArchiveGenerateConfig config, String campusid) {
         PatChildArchiveDetail detail = new PatChildArchiveDetail();
         detail.setArchiveType(config.getArchiveType());
-        detail.setSourceType(SOURCE_TYPE_OUTHOSP);
+        detail.setFollowupPeriod(config.getFollowupPeriod());
+        detail.setSourceType(SpecificArchiveConstants.SOURCE_TYPE_OUTHOSP);
+        detail.setSourceBizId(patMedOuthosp.getId());
+        detail.setSourceBizNo(patMedOuthosp.getOuthospno());
         fillCommonChildDetail(detail, patMedOuthosp, patArchive, campusid);
         detail.setParentPhone(patArchive != null
                 ? firstNotBlank(patArchive.getTelcode(), patMedOuthosp.getTelcode())
@@ -203,6 +519,104 @@
             detail.setNutritionIcd10Code(patMedOuthosp.getIcd10code());
             detail.setNutritionDiagName(patMedOuthosp.getDiagname());
         }
+        return detail;
+    }
+
+    private PatMaternityArchiveDetail buildInhospMaternityDetail(InhospArchiveContext context,
+                                                                 PatSpecificArchiveGenerateConfig config) {
+        PatMaternityArchiveDetail detail = new PatMaternityArchiveDetail();
+        detail.setArchiveType(config.getArchiveType());
+        detail.setFollowupPeriod(config.getFollowupPeriod());
+        detail.setSourceType(SpecificArchiveConstants.SOURCE_TYPE_INHOSP_FOLLOWUP);
+        detail.setSourceBizId(inInhospid(context));
+        detail.setSourceBizNo(inInhospno(context));
+        detail.setSourceSubId(context.subtask.getId());
+        detail.setOuthospno(null);
+        detail.setInhospno(inInhospno(context));
+        detail.setSerialnum(inSerialnum(context));
+        detail.setPatid(context.patid);
+        detail.setPatname(firstNotBlank(context.patArchive == null ? null : context.patArchive.getName(),
+                context.inhosp == null ? null : context.inhosp.getPatname()));
+        detail.setBirthdate(context.patArchive == null ? null : context.patArchive.getBirthdate());
+        detail.setIdcardno(firstNotBlank(context.patArchive == null ? null : context.patArchive.getIdcardno(),
+                context.inhosp == null ? null : context.inhosp.getIdcardno()));
+        detail.setPhone(firstNotBlank(context.patArchive == null ? null : context.patArchive.getTelcode(),
+                context.inhosp == null ? null : context.inhosp.getTelcode()));
+        detail.setSex(firstNonNull(context.patArchive == null ? null : context.patArchive.getSex(),
+                context.inhosp == null ? null : context.inhosp.getSex(),
+                context.subtask.getSex()));
+        detail.setDiagTime(context.diagTime);
+        detail.setArchiveTime(new Date());
+        detail.setDoctorCode(inDrcode(context));
+        detail.setDoctorName(inDrname(context));
+        detail.setManagementDoctorCode(firstNotBlank(context.inhosp == null ? null : context.inhosp.getManagementDoctorCode(),
+                inDrcode(context)));
+        detail.setManagementDoctorName(firstNotBlank(context.inhosp == null ? null : context.inhosp.getManagementDoctor(),
+                inDrname(context)));
+        detail.setFirstDoctorCode(inDrcode(context));
+        detail.setFirstDoctorName(inDrname(context));
+        detail.setDeptcode(context.deptCode);
+        detail.setDeptname(context.deptName);
+        detail.setWardcode(context.wardCode);
+        detail.setWardname(context.wardName);
+        detail.setIcd10code(context.icd10Code);
+        detail.setDiagname(context.diagName);
+        detail.setAddress(context.patArchive == null ? null : context.patArchive.getPlaceOfResidence());
+        detail.setRegisterUser("浣忛櫌闅忚");
+        detail.setOrgid(context.orgid);
+        detail.setCampusid(context.campusid);
+        detail.setDelFlag("0");
+        return detail;
+    }
+
+    private PatChildArchiveDetail buildInhospChildDetail(InhospArchiveContext context,
+                                                         PatSpecificArchiveGenerateConfig config) {
+        PatChildArchiveDetail detail = new PatChildArchiveDetail();
+        detail.setArchiveType(config.getArchiveType());
+        detail.setFollowupPeriod(config.getFollowupPeriod());
+        detail.setSourceType(SpecificArchiveConstants.SOURCE_TYPE_INHOSP_FOLLOWUP);
+        detail.setSourceBizId(inInhospid(context));
+        detail.setSourceBizNo(inInhospno(context));
+        detail.setSourceSubId(context.subtask.getId());
+        detail.setOuthospno(null);
+        detail.setInhospno(inInhospno(context));
+        detail.setSerialnum(inSerialnum(context));
+        detail.setPatid(context.patid);
+        detail.setPatname(firstNotBlank(context.patArchive == null ? null : context.patArchive.getName(),
+                context.inhosp == null ? null : context.inhosp.getPatname()));
+        detail.setBirthdate(context.patArchive == null ? null : context.patArchive.getBirthdate());
+        detail.setIdcardno(firstNotBlank(context.patArchive == null ? null : context.patArchive.getIdcardno(),
+                context.inhosp == null ? null : context.inhosp.getIdcardno()));
+        detail.setPhone(firstNotBlank(context.patArchive == null ? null : context.patArchive.getTelcode(),
+                context.inhosp == null ? null : context.inhosp.getTelcode()));
+        detail.setSex(firstNonNull(context.patArchive == null ? null : context.patArchive.getSex(),
+                context.inhosp == null ? null : context.inhosp.getSex(),
+                context.subtask.getSex()));
+        detail.setDiagTime(context.diagTime);
+        detail.setArchiveTime(new Date());
+        detail.setDoctorCode(inDrcode(context));
+        detail.setDoctorName(inDrname(context));
+        detail.setManagementDoctorCode(firstNotBlank(context.inhosp == null ? null : context.inhosp.getManagementDoctorCode(),
+                inDrcode(context)));
+        detail.setManagementDoctorName(firstNotBlank(context.inhosp == null ? null : context.inhosp.getManagementDoctor(),
+                inDrname(context)));
+        detail.setDeptcode(context.deptCode);
+        detail.setDeptname(context.deptName);
+        detail.setWardcode(context.wardCode);
+        detail.setWardname(context.wardName);
+        detail.setIcd10code(context.icd10Code);
+        detail.setDiagname(context.diagName);
+        detail.setParentPhone(firstNotBlank(context.patArchive == null ? null : context.patArchive.getTelcode(),
+                context.inhosp == null ? null : context.inhosp.getTelcode()));
+        detail.setParentAddress(context.patArchive == null ? null : context.patArchive.getPlaceOfResidence());
+        if ("1".equals(config.getArchiveType())) {
+            detail.setNutritionIcd10Code(context.icd10Code);
+            detail.setNutritionDiagName(context.diagName);
+        }
+        detail.setRegisterUser("浣忛櫌闅忚");
+        detail.setOrgid(context.orgid);
+        detail.setCampusid(context.campusid);
+        detail.setDelFlag("0");
         return detail;
     }
 
@@ -287,6 +701,85 @@
         return CollectionUtils.isNotEmpty(archives) ? archives.get(0) : null;
     }
 
+    private PatArchive resolvePatArchive(Long patid, PatMedInhosp inhosp) {
+        if (patid != null) {
+            PatArchive archive = patArchiveMapper.selectPatArchiveByPatid(patid);
+            if (archive != null) {
+                return archive;
+            }
+        }
+        Long inhospPatid = inhosp == null ? null : inhosp.getPatid();
+        return inhospPatid == null ? null : patArchiveMapper.selectPatArchiveByPatid(inhospPatid);
+    }
+
+    private PatMedInhosp resolveInhosp(ServiceSubtask subtask) {
+        if (subtask.getInhospid() != null) {
+            PatMedInhosp inhosp = inhospVisitFacade.selectPatMedInhospByInhospid(subtask.getInhospid());
+            if (inhosp != null) {
+                return inhosp;
+            }
+        }
+        if (StringUtils.isNotBlank(subtask.getHospno())) {
+            PatMedInhosp query = new PatMedInhosp();
+            query.setInhospno(subtask.getHospno());
+            query.setOrgid(subtask.getOrgid());
+            List<PatMedInhosp> list = inhospVisitFacade.selectPatMedInhosp(query);
+            if (CollectionUtils.isNotEmpty(list)) {
+                return list.get(0);
+            }
+        }
+        return null;
+    }
+
+    private void recordLog(InhospArchiveContext context, PatSpecificArchiveGenerateConfig config,
+                           String deptCategory, String archiveType, String result, Long archiveId, String msg) {
+        PatSpecificArchiveGenerateLog log = new PatSpecificArchiveGenerateLog();
+        log.setSourceType(SpecificArchiveConstants.SOURCE_TYPE_INHOSP_FOLLOWUP);
+        log.setSourceBizId(inInhospid(context));
+        log.setSourceBizNo(inInhospno(context));
+        log.setSourceSubId(context.subtask.getId());
+        log.setPatid(context.patid);
+        log.setOrgid(context.orgid);
+        log.setCampusid(context.campusid);
+        log.setDeptCategory(deptCategory);
+        log.setArchiveType(archiveType);
+        log.setConfigId(config == null || config.getId() == null
+                ? SpecificArchiveConstants.NO_CONFIG_ID : config.getId().intValue());
+        log.setArchiveId(archiveId);
+        log.setProcessResult(result);
+        log.setProcessMsg(msg);
+        PatSpecificArchiveGenerateLog old = patSpecificArchiveGenerateLogService.selectBySourceSubAndConfig(
+                log.getSourceType(), log.getSourceSubId(), log.getConfigId());
+        int retry = old == null || old.getRetryCount() == null ? 0 : old.getRetryCount();
+        if (SpecificArchiveConstants.RESULT_FAILED.equals(result)) {
+            retry++;
+        }
+        log.setRetryCount(retry);
+        patSpecificArchiveGenerateLogService.saveOrUpdate(log);
+    }
+
+    private Long inInhospid(InhospArchiveContext context) {
+        return firstNonNull(context.inhosp == null ? null : context.inhosp.getInhospid(),
+                context.subtask.getInhospid());
+    }
+
+    private String inInhospno(InhospArchiveContext context) {
+        return firstNotBlank(context.inhosp == null ? null : context.inhosp.getInhospno(),
+                context.subtask.getHospno());
+    }
+
+    private String inSerialnum(InhospArchiveContext context) {
+        return context.inhosp == null ? null : context.inhosp.getSerialnum();
+    }
+
+    private String inDrcode(InhospArchiveContext context) {
+        return firstNotBlank(context.inhosp == null ? null : context.inhosp.getDrcode(), context.subtask.getDrcode());
+    }
+
+    private String inDrname(InhospArchiveContext context) {
+        return firstNotBlank(context.inhosp == null ? null : context.inhosp.getDrname(), context.subtask.getDrname());
+    }
+
     private List<String> parseCodes(String raw) {
         if (StringUtils.isBlank(raw)) {
             return Collections.emptyList();
@@ -312,8 +805,42 @@
                 .collect(Collectors.toList());
     }
 
-    private String firstNotBlank(String first, String second) {
-        return StringUtils.isNotBlank(first) ? first : second;
+    private List<String> parseCsv(String raw) {
+        if (StringUtils.isBlank(raw)) {
+            return Collections.emptyList();
+        }
+        return Arrays.stream(raw.split(","))
+                .map(String::trim)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.toList());
+    }
+
+    private String firstNotBlank(String... values) {
+        if (values == null) {
+            return null;
+        }
+        for (String value : values) {
+            if (StringUtils.isNotBlank(value)) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+    private <T> T firstNonNull(T... values) {
+        if (values == null) {
+            return null;
+        }
+        for (T value : values) {
+            if (value != null) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+    private Date firstDate(Date first, Date second) {
+        return first != null ? first : second;
     }
 
     private boolean containsIgnoreCase(List<String> source, String target) {
@@ -326,4 +853,30 @@
     private boolean equalsIgnoreCase(String first, String second) {
         return first != null && second != null && first.trim().equalsIgnoreCase(second.trim());
     }
+
+    private String truncateMsg(String msg) {
+        if (msg == null) {
+            return null;
+        }
+        return msg.length() <= 900 ? msg : msg.substring(0, 900);
+    }
+
+    /**
+     * 浣忛櫌闅忚鐢熸垚妗f鏃剁敤鍒扮殑涓婁笅鏂囥��
+     */
+    private static class InhospArchiveContext {
+        private ServiceSubtask subtask;
+        private PatMedInhosp inhosp;
+        private PatArchive patArchive;
+        private Long patid;
+        private String orgid;
+        private String campusid;
+        private String deptCode;
+        private String deptName;
+        private String wardCode;
+        private String wardName;
+        private String icd10Code;
+        private String diagName;
+        private Date diagTime;
+    }
 }

--
Gitblit v1.9.3