# 门诊医生站手术申请未生成预收费明细记录问题深度分析报告 ## 一、问题概述 门诊医生站手术申请保存后,门诊收费系统无法查询到对应的预收费明细记录。 ## 二、已做的修复 已将 `SurgeryAppServiceImpl.java` 中的 `ChargeItem` 状态从 `DRAFT` 改为 `PLANNED`: ```java // 第350行 chargeItem.setStatusEnum(ChargeItemStatus.PLANNED.getValue()); // 收费状态:待收费 ``` ## 三、深入分析发现的问题 ### 3.1 前端提交数据检查 **文件**: `openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue` 前端表单包含费用字段: - `surgeryFee` - 手术费用(第419行) - `anesthesiaFee` - 麻醉费用(第426行) - `totalFee` - 总费用(通过计算属性 `totalCalculatedFee` 自动计算并同步到表单,第564-583行) 提交时调用 API: - 新增:`addSurgery(form.value)`(第1050行) - 修改:`updateSurgery(form.value)`(第1066行) **结论**: 前端正确传递了费用字段,问题不在前端。 ### 3.2 后端收费生成逻辑分析 **文件**: `openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java` 手术申请生成 ChargeItem 的代码(第348-369行): ```java ChargeItem chargeItem = new ChargeItem(); chargeItem.setStatusEnum(ChargeItemStatus.PLANNED.getValue()); // 收费状态:待收费 chargeItem.setBusNo("CI" + serviceRequest.getBusNo()); chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); chargeItem.setPatientId(surgeryDto.getPatientId()); chargeItem.setContextEnum(3); // 类型:3-诊疗 chargeItem.setEncounterId(surgeryDto.getEncounterId()); chargeItem.setAccountId(accountId); chargeItem.setDefinitionId(surgeryId); chargeItem.setEntererId(practitionerId); chargeItem.setEnteredDate(curDate); chargeItem.setServiceTable(CommonConstants.TableName.WOR_SERVICE_REQUEST); chargeItem.setServiceId(serviceRequest.getId()); chargeItem.setProductTable("cli_surgery"); // 【问题1】产品表是手术表 chargeItem.setProductId(surgeryId); // 【问题2】产品ID是手术ID chargeItem.setRequestingOrgId(orgId); chargeItem.setQuantityValue(BigDecimal.valueOf(1)); chargeItem.setQuantityUnit("次"); chargeItem.setUnitPrice(surgeryDto.getSurgeryFee() != null ? surgeryDto.getSurgeryFee() : new BigDecimal("0.0")); chargeItem.setTotalPrice(surgeryDto.getTotalFee() != null ? surgeryDto.getTotalFee() : new BigDecimal("0.0")); chargeItemService.save(chargeItem); ``` ### 3.3 门诊收费查询逻辑分析 **文件**: `openhis-server-new/openhis-application/src/main/resources/mapper/chargemanage/OutpatientChargeAppMapper.xml` 关键 SQL 查询(第67-148行): ```sql SELECT T1.encounter_id, T1.id, T1.patient_id, T1.context_enum, T1.status_enum, ... CASE WHEN T1.context_enum = #{activity} THEN T2."name" WHEN T1.context_enum = #{medication} THEN T3."name" WHEN T1.context_enum = #{device} THEN T4."name" END AS item_name, FROM adm_charge_item AS T1 LEFT JOIN wor_activity_definition AS T2 ON T1.context_enum = #{activity} AND T1.product_id = T2.id LEFT JOIN med_medication_definition AS T3 ON T1.context_enum = #{medication} AND T1.product_id = T3.id LEFT JOIN adm_device_definition AS T4 ON T1.context_enum = #{device} AND T1.product_id = T4.id -- ... 其他条件 WHERE T1.encounter_id = #{encounterId} AND T1.status_enum IN (#{planned}, #{billable}, #{billed}, #{refunding}, #{refunded}, #{partRefund}) AND T1.context_enum != #{register} AND T1.delete_flag = '0' ``` **参数值**: - `activity` = 3 (ChargeItemContext.ACTIVITY.getValue()) - `planned` = 1 (ChargeItemStatus.PLANNED.getValue()) ### 3.4 核心问题定位 #### 问题1:ChargeItemContext 枚举定义 **文件**: `openhis-common/src/main/java/com/openhis/common/enums/ChargeItemContext.java` ```java public enum ChargeItemContext implements HisEnumInterface { MEDICATION(1, "1", "药品"), DEVICE(2, "2", "耗材"), ACTIVITY(3, "3", "项目"), // 诊疗项目 REGISTER(4, "4", "挂号"); } ``` #### 问题2:数据关联不匹配(根本原因) 手术申请生成的 ChargeItem: | 字段 | 值 | 说明 | |------|-----|------| | contextEnum | 3 | ACTIVITY(项目) | | productTable | "cli_surgery" | 手术表 | | productId | surgeryId | 手术ID | 门诊收费 SQL 查询逻辑: - 当 `context_enum = 3 (ACTIVITY)` 时,关联 `wor_activity_definition` 表 - SQL: `LEFT JOIN wor_activity_definition AS T2 ON T1.context_enum = #{activity} AND T1.product_id = T2.id` **核心问题**: 1. 手术申请保存的 `product_id` 是手术ID(cli_surgery表的ID) 2. 但 SQL 查询时关联的是 `wor_activity_definition` 表 3. 手术ID在 `wor_activity_definition` 表中不存在 4. 导致 LEFT JOIN 返回 NULL,手术收费记录无法显示 ### 3.5 对比其他申请类型的收费生成 #### 检查申请(ExamApplyController.java) ```java chargeItem.setContextEnum(2); // 类型:2=耗材(不是诊疗!) chargeItem.setProductTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION); chargeItem.setProductId(0L); ``` #### 住院申请单(RequestFormManageAppServiceImpl.java) ```java surgeryChargeItem.setContextEnum(3); // 3-诊疗 surgeryChargeItem.setProductTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION); surgeryChargeItem.setProductId(activityList.get(0).getAdviceDefinitionId()); // 诊疗定义ID ``` **差异总结**: | 申请类型 | contextEnum | productTable | productId | |----------|-------------|--------------|-----------| | 手术申请(门诊) | 3 (ACTIVITY) | cli_surgery | surgeryId | | 检查申请 | 2 (DEVICE) | wor_activity_definition | 0L | | 住院申请单 | 3 (ACTIVITY) | wor_activity_definition | adviceDefinitionId | ## 四、解决方案 ### 方案1:修改手术申请的 productTable 和 productId(推荐) 修改 `SurgeryAppServiceImpl.java` 第362-363行: ```java // 修改前 chargeItem.setProductTable("cli_surgery"); chargeItem.setProductId(surgeryId); // 修改后 chargeItem.setProductTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION); // 需要获取手术对应的诊疗项目定义ID chargeItem.setProductId(surgeryDefinitionId); // 从手术项目定义表中获取 ``` **注意**:此方案需要手术项目与诊疗项目定义有对应关系。 ### 方案2:修改门诊收费查询 SQL 修改 `OutpatientChargeAppMapper.xml`,增加对 `cli_surgery` 表的关联: ```xml ``` ### 方案3:修改 ChargeItem 保存逻辑(临时方案) 如果手术项目暂时没有对应的诊疗项目定义,可以: ```java // 设置 productTable 为 wor_activity_definition,但 productId 设为 0 chargeItem.setProductTable(CommonConstants.TableName.WOR_ACTIVITY_DEFINITION); chargeItem.setProductId(0L); // 在 item_name 或其他字段中保存手术名称 ``` ## 五、额外发现的问题 ### 5.1 检查申请的 contextEnum 设置错误 在 `ExamApplyController.java` 第249行: ```java chargeItem.setContextEnum(2); // 类型:2=诊疗 ``` 但实际上 `2` 对应的是 `ChargeItemContext.DEVICE`(耗材),不是诊疗。正确的应该是: ```java chargeItem.setContextEnum(ChargeItemContext.ACTIVITY.getValue()); // 3 ``` ### 5.2 手术申请缺少处方号 对比检查申请,手术申请的 ChargeItem 没有设置 `prescriptionNo` 字段,可能导致收费查询时无法关联到处方信息。 ## 六、修复建议优先级 1. **高优先级**:修改手术申请的 `productTable` 和 `productId`,使其与门诊收费 SQL 查询兼容 2. **中优先级**:增加手术申请 ChargeItem 的 `prescriptionNo` 字段设置 3. **低优先级**:修复检查申请的 `contextEnum` 设置错误 ## 七、验证步骤 1. 修改代码后,重新编译部署 2. 在门诊医生站创建新的手术申请 3. 检查 `adm_charge_item` 表,确认记录已生成且字段正确 4. 在门诊收费系统查询该患者的收费明细,确认手术费用能正常显示 5. 测试收费、结算流程是否正常 ## 八、相关文件清单 | 文件路径 | 说明 | |----------|------| | `openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue` | 前端手术申请组件 | | `openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java` | 手术申请服务实现 | | `openhis-server-new/openhis-application/src/main/resources/mapper/chargemanage/OutpatientChargeAppMapper.xml` | 门诊收费查询Mapper | | `openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientChargeAppServiceImpl.java` | 门诊收费服务实现 | | `openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/ChargeItemContext.java` | 收费项目类型枚举 | | `openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/domain/ChargeItem.java` | 收费项实体类 | | `openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/ExamApplyController.java` | 检查申请控制器(对比参考) | | `openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/appservice/impl/RequestFormManageAppServiceImpl.java` | 住院申请单服务(对比参考) |