LIJU 2 周之前
父節點
當前提交
82278ecc53

+ 5 - 0
src/main/java/thyyxxk/webserver/controller/medicalinsurance/SiZyController.java

@@ -71,6 +71,11 @@ public class SiZyController {
         return ResultVoUtil.success(service.revokeUploadFees(p));
     }
 
+    @PostMapping("/revokeWorkInjuryUploadFees")
+    public ResultVo<String> revokeWorkInjuryUploadFees(@RequestBody ZyPatientInfo p) {
+        return ResultVoUtil.success(service.revokeWorkInjuryUploadFees(p));
+    }
+
     @PostMapping("/hospitalizationPreSettlement")
     public ResultVo<String> hospitalizationPreSettlement(@RequestBody ZyPatientInfo p) {
         return ResultVoUtil.success(service.hospitalizationPreSettlement(p, zyYbData));

+ 8 - 0
src/main/java/thyyxxk/webserver/dao/his/medicalinsurance/SiZyDao.java

@@ -251,4 +251,12 @@ public interface SiZyDao {
     @Update("update t_si_sign_in set sign_no=#{signNo}, " +
             "sign_date=getdate() where id='medInsurSignIn'")
     void updateSignNo(String signNo);
+
+    // 查询某患者某次住院所有已上传但未结算的明细号(包含录入和上账状态)
+    @Select("SELECT detail_sn FROM zy_detail_charge WHERE inpatient_no = #{patNo} AND admiss_times = #{times} AND ledger_sn = #{ledgerSn} AND trans_flag_yb = 1 AND charge_status IN ('1', '2')")
+    List<Integer> selectAllUploadedDetailSns(@Param("patNo") String patNo, @Param("times") Integer times, @Param("ledgerSn") Integer ledgerSn);
+
+    // 根据明细号查处方号
+    @Select("SELECT order_no FROM zy_detail_charge WHERE inpatient_no = #{patNo} AND admiss_times = #{times} AND detail_sn = #{detailSn}")
+    String selectRxnoByDetailSn(@Param("patNo") String patNo, @Param("times") Integer times, @Param("detailSn") Integer detailSn);
 }

+ 19 - 0
src/main/java/thyyxxk/webserver/service/medicalinsurance/ExecService.java

@@ -250,4 +250,23 @@ public class ExecService {
             return object;
         }
     }
+
+    /**
+     * 工伤接口URL
+     */
+    // 模拟接口地址(当前使用)
+    private static final String WORK_INJURY_API_URL = "http://130.150.161.72:9206/thyy/api/public/injury/workinjury";
+    // 真实接口地址(注释掉,需要时手动切换)
+    // private static final String WORK_INJURY_API_URL = "http://localhost:8321/api/entry/workinjury";
+
+    /**
+     * 执行工伤接口调用(工伤接口使用不同的请求头格式)
+     */
+    public JSONObject executeWorkInjuryTrade(JSONObject input) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.add("Content-Type", "application/json");
+        // 工伤接口可能不需要医保接口的认证头,直接使用简单的JSON头
+        return template.postForObject(WORK_INJURY_API_URL,
+                new HttpEntity<>(input, headers), JSONObject.class);
+    }
 }

+ 272 - 0
src/main/java/thyyxxk/webserver/service/medicalinsurance/SiZyService.java

@@ -30,6 +30,7 @@ import thyyxxk.webserver.utils.*;
 
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.ArrayList;
 
 /**
  * @description: 住院医保交易
@@ -741,4 +742,275 @@ public class SiZyService {
         dao.updateSettleType(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
         dao.updateChargeStatus(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
     }
+
+    public String revokeWorkInjuryUploadFees(ZyPatientInfo p) {
+        SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
+        if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的工伤在院信息!");
+        }
+        
+        // 根据传入的明细号决定撤销方式
+        if (null == p.getDetailSns() || p.getDetailSns().isEmpty()) {
+            // 撤销全部:只传门诊/住院流水号,处方号和处方流水号为空
+            return revokeAllWorkInjuryFees(p, siPatInfo);
+        } else {
+            // 撤销指定明细:需要遍历每个明细号
+            return revokeSpecificWorkInjuryFees(p, siPatInfo);
+        }
+    }
+    
+    /**
+     * 撤销全部工伤费用
+     */
+    private String revokeAllWorkInjuryFees(ZyPatientInfo p, SiPatInfo siPatInfo) {
+        // 构建工伤撤销请求(处方明细撤销)
+        JSONObject input = new JSONObject();
+        input.put("action", "transaction");
+        input.put("transactionName", "2205");
+        
+        JSONObject businessParams = new JSONObject();
+        businessParams.put("ipt_otp_no", siPatInfo.getMdtrtId());  // 门诊/住院流水号
+        businessParams.put("rxno", "");  // 处方号为空
+        businessParams.put("feedetl_sn", "");  // 处方流水号为空
+        
+        input.put("businessParams", businessParams);
+        
+        // 调用工伤撤销接口
+        JSONObject result = exec.executeWorkInjuryTrade(input);
+        
+        if (null == result) {
+            throw new BizException(ExceptionEnum.NETWORK_ERROR, "工伤撤销接口调用失败");
+        }
+        
+        // 工伤接口返回结果处理(支持模拟接口和真实接口切换)
+        Integer infcode = extractWorkInjuryResultCode(result);
+        
+        if (null == infcode) {
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "工伤撤销接口返回结果解析失败");
+        }
+        
+        // 构造工伤日志input(参考工伤预结算写法)
+        JSONObject logInput = new JSONObject();
+        if (result != null && result.containsKey("data")) {
+            JSONObject data = result.getJSONObject("data");
+            if (data.containsKey("transformed_parameters")) {
+                JSONObject transformedParams = data.getJSONObject("transformed_parameters");
+                logInput.put("infno", transformedParams.getString("infno"));
+                logInput.put("insuplc_admdvs", "");
+                logInput.put("msgid", transformedParams.getString("msgid"));
+                logInput.put("opter", transformedParams.getString("opter"));
+            } else {
+                logInput.put("infno", "2205"); // 工伤撤销接口号
+                logInput.put("insuplc_admdvs", "");
+                logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
+                logInput.put("opter", p.getStaffId());
+            }
+        } else {
+            logInput.put("infno", "2205");
+            logInput.put("insuplc_admdvs", "");
+            logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
+            logInput.put("opter", p.getStaffId());
+        }
+        logDao.insert(new SiLog(logInput, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
+        
+        if (infcode == 0) {
+            // 撤销成功,更新数据库状态
+            dao.revokeAllUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
+            dao.resetFundpayAmt(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
+            
+            QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
+            wrapper.eq("pat_no", p.getInpatientNo());
+            wrapper.eq("times", p.getAdmissTimes());
+            wrapper.eq("ledger_sn", p.getLedgerSn());
+            chrgtmpdao.delete(wrapper);
+            
+            return "工伤撤销费用成功。";
+        } else {
+            String errorMsg = extractWorkInjuryErrorMessage(result);
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "工伤撤销失败:" + errorMsg);
+        }
+    }
+    
+    /**
+     * 撤销指定工伤费用明细
+     */
+    private String revokeSpecificWorkInjuryFees(ZyPatientInfo p, SiPatInfo siPatInfo) {
+        List<Integer> successDetailSns = new ArrayList<>();
+        List<Integer> failedDetailSns = new ArrayList<>();
+        
+        // 遍历每个明细号,逐个撤销
+        for (Integer detailSn : p.getDetailSns()) {
+            // 构建工伤撤销请求(处方明细撤销)
+            JSONObject input = new JSONObject();
+            input.put("action", "transaction");
+            input.put("transactionName", "2205");
+            
+            JSONObject businessParams = new JSONObject();
+            businessParams.put("ipt_otp_no", siPatInfo.getMdtrtId());  // 门诊/住院流水号
+            
+            // 获取对应的处方号
+            String rxno = dao.selectRxnoByDetailSn(p.getInpatientNo(), p.getAdmissTimes(), detailSn);
+            
+            if (StringUtil.isBlank(rxno)) {
+                // 如果处方号为空,只传门诊/住院流水号,不传处方号和处方流水号
+                // 这样会撤销该门诊/住院流水号下所有未结算处方
+                businessParams.put("rxno", "");
+                businessParams.put("feedetl_sn", "");
+            } else {
+                // 如果处方号有值,传完整的参数
+                businessParams.put("rxno", rxno);
+                businessParams.put("feedetl_sn", detailSn.toString());
+            }
+            
+            input.put("businessParams", businessParams);
+            
+            // 调用工伤撤销接口
+            JSONObject result = exec.executeWorkInjuryTrade(input);
+            
+            if (null == result) {
+                log.error("工伤撤销接口调用失败,明细:{}", detailSn);
+                failedDetailSns.add(detailSn);
+                continue; // 继续撤销下一个,不中断整个流程
+            }
+            
+            // 工伤接口返回结果处理(支持模拟接口和真实接口切换)
+            Integer infcode = extractWorkInjuryResultCode(result);
+            
+            if (null == infcode) {
+                log.error("工伤撤销接口返回结果解析失败,明细:{}", detailSn);
+                failedDetailSns.add(detailSn);
+                continue;
+            }
+            
+            // 构造工伤日志input(参考工伤预结算写法)
+            JSONObject logInput = new JSONObject();
+            if (result != null && result.containsKey("data")) {
+                JSONObject data = result.getJSONObject("data");
+                if (data.containsKey("transformed_parameters")) {
+                    JSONObject transformedParams = data.getJSONObject("transformed_parameters");
+                    logInput.put("infno", transformedParams.getString("infno"));
+                    logInput.put("insuplc_admdvs", "");
+                    logInput.put("msgid", transformedParams.getString("msgid"));
+                    logInput.put("opter", transformedParams.getString("opter"));
+                } else {
+                    logInput.put("infno", "2205"); // 工伤撤销接口号
+                    logInput.put("insuplc_admdvs", "");
+                    logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
+                    logInput.put("opter", p.getStaffId());
+                }
+            } else {
+                logInput.put("infno", "2205");
+                logInput.put("insuplc_admdvs", "");
+                logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
+                logInput.put("opter", p.getStaffId());
+            }
+            logDao.insert(new SiLog(logInput, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
+            
+            if (infcode == 0) {
+                log.info("工伤撤销成功,明细:{}", detailSn);
+                successDetailSns.add(detailSn);
+            } else {
+                String errorMsg = extractWorkInjuryErrorMessage(result);
+                log.error("工伤撤销失败,明细:{},错误:{}", detailSn, errorMsg);
+                failedDetailSns.add(detailSn);
+            }
+        }
+        
+        // 根据撤销结果分别更新数据库状态
+        if (successDetailSns.isEmpty()) {
+            log.warn("工伤撤销全部失败,患者:{},明细数:{}", p.getInpatientNo(), p.getDetailSns().size());
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "工伤撤销全部失败,请检查网络连接和接口状态。");
+        }
+        
+        // 更新数据库
+        if (successDetailSns.size() == p.getDetailSns().size()) {
+            // 全部撤销成功
+            log.info("工伤撤销全部成功,患者:{},明细数:{}", p.getInpatientNo(), successDetailSns.size());
+            dao.revokePartUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), successDetailSns);
+            
+            QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
+            wrapper.eq("pat_no", p.getInpatientNo());
+            wrapper.eq("times", p.getAdmissTimes());
+            wrapper.eq("ledger_sn", p.getLedgerSn());
+            wrapper.in("feedetl_sn", successDetailSns);
+            chrgtmpdao.delete(wrapper);
+        } else {
+            // 部分撤销成功,只更新成功撤销的明细
+            log.info("工伤撤销部分成功,患者:{},成功:{},失败:{}", 
+                    p.getInpatientNo(), successDetailSns.size(), failedDetailSns.size());
+            dao.revokePartUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), successDetailSns);
+            
+            QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
+            wrapper.eq("pat_no", p.getInpatientNo());
+            wrapper.eq("times", p.getAdmissTimes());
+            wrapper.eq("ledger_sn", p.getLedgerSn());
+            wrapper.in("feedetl_sn", successDetailSns);
+            chrgtmpdao.delete(wrapper);
+        }
+        
+        log.info("工伤撤销流程完成,患者:{},成功撤销:{},失败撤销:{}", 
+                p.getInpatientNo(), successDetailSns.size(), failedDetailSns.size());
+        
+        if (failedDetailSns.isEmpty()) {
+            return "工伤撤销费用成功。";
+        } else {
+            return String.format("工伤撤销部分成功。成功:%d,失败:%d", successDetailSns.size(), failedDetailSns.size());
+        }
+    }
+
+    /**
+     * 工伤接口返回结果代码提取(支持模拟接口和真实接口切换)
+     */
+    private Integer extractWorkInjuryResultCode(JSONObject result) {
+        if (result == null) {
+            return null;
+        }
+        
+        // 模拟接口返回结构:result.getJSONObject("data").getJSONObject("data").getString("infcode")
+        // 真实接口返回结构:result.getJSONObject("data").getString("infcode")
+        
+        // 模拟接口处理(当前使用)
+        if (result.containsKey("data") && result.getJSONObject("data").containsKey("data")) {
+            JSONObject innerData = result.getJSONObject("data").getJSONObject("data");
+            return innerData != null ? innerData.getInteger(RESULT_CODE) : null;
+        }
+        // 真实接口处理(注释掉,需要时手动切换)
+        // else if (result.containsKey("data")) {
+        //     JSONObject data = result.getJSONObject("data");
+        //     return data != null ? data.getInteger(RESULT_CODE) : null;
+        // }
+        
+        return null;
+    }
+
+    /**
+     * 工伤接口错误信息提取(支持模拟接口和真实接口切换)
+     */
+    private String extractWorkInjuryErrorMessage(JSONObject result) {
+        if (result == null) {
+            return "未知错误";
+        }
+        
+        // 模拟接口返回结构:result.getJSONObject("data").getJSONObject("data").getString("err_msg")
+        // 真实接口返回结构:result.getJSONObject("data").getString("err_msg")
+        
+        // 模拟接口处理(当前使用)
+        if (result.containsKey("data") && result.getJSONObject("data").containsKey("data")) {
+            JSONObject innerData = result.getJSONObject("data").getJSONObject("data");
+            if (innerData != null) {
+                String errorMsg = innerData.getString(ERROR_MESSAGE);
+                return StringUtil.isBlank(errorMsg) ? "未知错误" : errorMsg;
+            }
+        }
+        // 真实接口处理(注释掉,需要时手动切换)
+        // else if (result.containsKey("data")) {
+        //     JSONObject data = result.getJSONObject("data");
+        //     if (data != null) {
+        //         String errorMsg = data.getString(ERROR_MESSAGE);
+        //         return StringUtil.isBlank(errorMsg) ? "未知错误" : errorMsg;
+        //     }
+        // }
+        
+        return "未知错误";
+    }
 }

+ 198 - 0
医保接口数据库操作详细分析.md

@@ -0,0 +1,198 @@
+# 医保接口数据库操作详细分析
+
+## 1. admissRegister 方法数据库操作
+
+### 1.1 `t_si_log` 表 - 医保接口调用日志表
+
+#### **操作类型**:INSERT
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `msgid` | String | `input.getString("msgid")` | 医保接口请求消息ID |
+| `infno` | String | `input.getString("infno")` | 医保接口功能号 |
+| `insuplc_admdvs` | String | `input.getString("insuplc_admdvs")` | 医保统筹区划 |
+| `opter` | String | `input.getString("opter")` | 经办人 |
+| `body` | String | `input.toJSONString()` | 完整的请求体JSON |
+| `result` | String | `result.toJSONString()` | 完整的响应体JSON |
+| `pat_no` | String | `p.getInpatientNo()` | 住院号 |
+| `times` | Integer | `p.getAdmissTimes()` | 住院次数 |
+| `ledger_sn` | Integer | `p.getLedgerSn()` | 账页号 |
+| `log_type` | Integer | 固定值 `1` | 住院类型 |
+| `create_datetime` | DateTime | `getdate()` | 记录生成时间 |
+| `infcode` | Integer | `result.getIntValue("infcode")` | 返回结果(0成功,-1失败) |
+| `psn_no` | String | `admMdtrtinfo.getPsnNo()` | 人员编号 |
+
+### 1.2 `t_si_pat_info` 表 - 患者医保信息表
+
+#### **操作类型**:UPDATE(afterAdmissRegister方法)
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `insuplc_admdvs` | String | `ybData.getInsuplcAdmdvs()` | 医保统筹区划 |
+| `psn_type` | String | `ybData.getPsnType()` | 人员类别 |
+| `emp_name` | String | `ybData.getEmpName()` | 单位名称 |
+| `balance` | BigDecimal | `ybData.getBalance()` | 账户余额 |
+| `mdtrt_id` | String | `output.getJSONObject("result").getString("mdtrt_id")` | 就诊ID(外部接口返回) |
+| `adm_reg_msgid` | String | `input.getString("msgid")` | 入院登记消息ID |
+
+### 1.3 `t_si_pat_info` 表 - 患者医保信息表
+
+#### **操作类型**:UPDATE(updateResponceType方法)
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `responce_type` | String | `dao.selectResponceType(admMdtrtinfo.getMedType())` | 响应类型(根据医保类型查询) |
+
+## 2. obtainBasicPersonInfo 方法数据库操作
+
+### 2.1 `mz_patient_mi` 表 - 门诊患者信息表
+
+#### **操作类型**:SELECT
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `social_no` | String | 数据库查询 | 身份证号 |
+| `name` | String | 数据库查询 | 姓名 |
+| `times` | Integer | 数据库查询 | 门诊次数 |
+| `certificate_type` | String | 数据库查询 | 证件类型 |
+
+### 2.2 `zy_ledger_file` 表 - 住院账页文件表
+
+#### **操作类型**:SELECT
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `ledger_sn` | Integer | `dao.selectMaxLedgerSn()` | 最大账页号 |
+
+### 2.3 `a_patient_mi` 表 - 患者基本信息表
+
+#### **操作类型**:SELECT
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `psn_cert_type` | String | `dao.selectPsnCertType()` | 人员证件类型 |
+
+### 2.4 `t_si_pat_info` 表 - 患者医保信息表
+
+#### **操作类型**:UPDATE(updatePsnIdetType方法)
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `psn_idet_type` | String | `psnBaseinfo.getPsnIdetType()` | 人员身份类型(外部接口返回) |
+
+#### **操作类型**:INSERT/UPDATE(insertSiZyInfoPsnNo/updateSiZyInfoPsnNo方法)
+
+**INSERT 字段及数据来源**:
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `pat_no` | String | `qryPsnBsInfo.getPatNo()` | 住院号 |
+| `times` | Integer | `qryPsnBsInfo.getTimes()` | 住院次数 |
+| `ledger_sn` | Integer | `qryPsnBsInfo.getLedgerSn()` | 账页号 |
+| `psn_no` | String | `psnBaseinfo.getPsnNo()` | 人员编号(外部接口返回) |
+| `psn_name` | String | `psnBaseinfo.getPsnName()` | 人员姓名(外部接口返回) |
+| `psn_cert_type` | String | `psnBaseinfo.getPsnCertType()` | 人员证件类型(外部接口返回) |
+| `certno` | String | `psnBaseinfo.getCertno()` | 证件号码(外部接口返回) |
+| `psn_idet_type` | String | `psnBaseinfo.getPsnIdetType()` | 人员身份类型(外部接口返回) |
+| `insuplc_admdvs` | String | `psnBaseinfo.getInsuplcAdmdvs()` | 医保统筹区划(外部接口返回) |
+| `psn_type` | String | `psnBaseinfo.getPsnType()` | 人员类别(外部接口返回) |
+| `emp_name` | String | `psnBaseinfo.getEmpName()` | 单位名称(外部接口返回) |
+| `balance` | BigDecimal | `psnBaseinfo.getBalance()` | 账户余额(外部接口返回) |
+
+**UPDATE 字段及数据来源**:
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `psn_no` | String | `psnBaseinfo.getPsnNo()` | 人员编号(外部接口返回) |
+| `psn_name` | String | `psnBaseinfo.getPsnName()` | 人员姓名(外部接口返回) |
+| `psn_cert_type` | String | `psnBaseinfo.getPsnCertType()` | 人员证件类型(外部接口返回) |
+| `certno` | String | `psnBaseinfo.getCertno()` | 证件号码(外部接口返回) |
+| `psn_idet_type` | String | `psnBaseinfo.getPsnIdetType()` | 人员身份类型(外部接口返回) |
+| `insuplc_admdvs` | String | `psnBaseinfo.getInsuplcAdmdvs()` | 医保统筹区划(外部接口返回) |
+| `psn_type` | String | `psnBaseinfo.getPsnType()` | 人员类别(外部接口返回) |
+| `emp_name` | String | `psnBaseinfo.getEmpName()` | 单位名称(外部接口返回) |
+| `balance` | BigDecimal | `psnBaseinfo.getBalance()` | 账户余额(外部接口返回) |
+
+### 2.5 `t_si_log` 表 - 医保接口调用日志表
+
+#### **操作类型**:INSERT
+
+| 字段名 | 数据类型 | 数据来源 | 备注 |
+|--------|----------|----------|------|
+| `msgid` | String | `input.getString("msgid")` | 医保接口请求消息ID |
+| `infno` | String | `input.getString("infno")` | 医保接口功能号 |
+| `insuplc_admdvs` | String | `input.getString("insuplc_admdvs")` | 医保统筹区划 |
+| `opter` | String | `input.getString("opter")` | 经办人 |
+| `body` | String | `input.toJSONString()` | 完整的请求体JSON |
+| `result` | String | `result.toJSONString()` | 完整的响应体JSON |
+| `pat_no` | String | `qryPsnBsInfo.getPatNo()` | 住院号 |
+| `times` | Integer | `qryPsnBsInfo.getTimes()` | 住院次数 |
+| `ledger_sn` | Integer | `qryPsnBsInfo.getLedgerSn()` | 账页号 |
+| `log_type` | Integer | 固定值 `1` | 住院类型 |
+| `create_datetime` | DateTime | `getdate()` | 记录生成时间 |
+| `infcode` | Integer | `result.getIntValue("infcode")` | 返回结果(0成功,-1失败) |
+| `psn_no` | String | `psnBaseinfo.getPsnNo()` | 人员编号(外部接口返回) |
+
+## 3. 外部接口数据来源详细说明
+
+### 3.1 admissRegister 方法外部接口数据
+
+**接口名称**:医保入院登记接口
+**接口功能号**:`SiFunction.ADMISSION_REGISTRATION`
+**返回数据结构**:
+```json
+{
+  "infcode": 0,
+  "output": {
+    "result": {
+      "mdtrt_id": "就诊ID"
+    }
+  }
+}
+```
+
+### 3.2 obtainBasicPersonInfo 方法外部接口数据
+
+**接口名称**:医保人员基本信息查询接口
+**接口功能号**:`SiFunction.OBTAIN_BASIC_PERSON_INFO`
+**返回数据结构**:
+```json
+{
+  "infcode": 0,
+  "output": {
+    "baseinfo": {
+      "psn_no": "人员编号",
+      "psn_name": "人员姓名",
+      "psn_cert_type": "人员证件类型",
+      "certno": "证件号码",
+      "psn_idet_type": "人员身份类型",
+      "insuplc_admdvs": "医保统筹区划",
+      "psn_type": "人员类别",
+      "emp_name": "单位名称",
+      "balance": "账户余额"
+    },
+    "idetinfo": [
+      {
+        "psn_idet_type": "人员身份类型"
+      }
+    ]
+  }
+}
+```
+
+## 4. 数据流向总结
+
+### 4.1 数据输入来源
+1. **前端参数**:住院号、住院次数、账页号等基础信息
+2. **外部医保接口**:人员信息、医保状态、账户余额等医保相关数据
+3. **本地数据库查询**:患者基础信息、医保类型等
+
+### 4.2 数据输出目标
+1. **`t_si_log`**:记录所有医保接口调用日志
+2. **`t_si_pat_info`**:存储患者医保信息和状态
+3. **其他相关表**:根据业务需要更新相关患者信息
+
+### 4.3 关键数据转换
+1. **外部接口数据 → 本地数据库字段**:将医保接口返回的数据映射到本地数据库字段
+2. **状态同步**:确保本地数据库中的医保状态与外部医保系统保持一致
+3. **日志记录**:完整记录所有医保接口调用过程,便于问题排查和审计