diff --git a/bug491_analysis.md b/bug491_analysis.md new file mode 100644 index 000000000..f07f1a13e --- /dev/null +++ b/bug491_analysis.md @@ -0,0 +1,50 @@ +# Bug #491 分析报告 + +## Bug 信息 +- **标题**: 【执行科室配置】保存配置时系统报错 +- **报错信息**: `Cannot invoke "com.openhis.administration.domain.Organization.getName()" because the return value of "com.openhis.administration.service..." is null` +- **严重程度**: 3 | **优先级**: 3 | **类型**: codeerror + +## 复现步骤 +1. 登录 HIS 系统 → 【系统管理】→【业务规则配置】→【执行科室配置】 +2. 左侧选择科室(如"超声诊断科") +3. 新增或修改某行的时间区间 +4. 点击【保存】按钮 +5. 顶部弹出红色错误提示(NPE) + +## 根因分析 + +### 文件定位 +- `openhis-server-new/.../appservice/impl/OrganizationLocationAppServiceImpl.java`(第161-175行) + +### 根本原因 +在 `addOrEditOrgLoc` 方法中,保存时会检查时间冲突。当发现冲突时,代码需要获取冲突记录的科室名称用于错误提示: + +```java +// 第171-172行 +Organization org = organizationService.getById(organizationLocation.getOrganizationId()); +String organizationName = org.getName(); // NPE 这里! +``` + +**问题**:`organizationService.getById()` 可能返回 `null`(当冲突记录的 `organizationId` 指向已被删除的机构时),直接调用 `.getName()` 导致 NPE。 + +### 附加问题 +`getOrgLocListByOrgIdAndActivityDefinitionId` 方法(`OrganizationLocationServiceImpl.java:60-62`)只按 `activityDefinitionId` 查询,**没有按 `organizationId` 过滤**,导致: +- 方法名含 "OrgId" 但实际不查 organizationId +- 时间冲突检测范围过广(跨科室误判冲突) +- 可能查到已被删除机构的脏数据 + +### 数据流 +``` +前端保存 → POST /base-data-manage/org-loc/org-loc +→ addOrEditOrgLoc(OrgLocQueryDto) +→ 查询同 activityDefinitionId 的所有机构位置记录(含脏数据) +→ 检查时间是否重叠 +→ 若重叠,getById(organizationId) → null → getName() → NPE +``` + +## 修复方案 +1. `OrganizationLocationAppServiceImpl.java` 第172行:增加 `org != null` 判空,回退为 `"未知科室"` +2. `IOrganizationLocationService.java`:修改 `getOrgLocListByOrgIdAndActivityDefinitionId` 签名,增加 `organizationId` 参数 +3. `OrganizationLocationServiceImpl.java`:查询条件增加 `.eq(OrganizationLocation::getOrganizationId, organizationId)` +4. `OrganizationLocationAppServiceImpl.java` 第162行:调用时传入 `orgLoc.getOrganizationId()` diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java index 3bf2ac301..e22699227 100755 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java @@ -159,7 +159,7 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation String activityName = activityDef != null ? activityDef.getName() : ""; List organizationLocationList = - organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getActivityDefinitionId()); + organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(), orgLoc.getActivityDefinitionId()); organizationLocationList = (orgLoc.getId() != null) ? organizationLocationList.stream().filter(item -> !orgLoc.getId().equals(item.getId())).toList() : organizationLocationList; @@ -169,7 +169,7 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation if (DateTimeUtils.isOverlap(organizationLocation.getStartTime(), organizationLocation.getEndTime(), orgLoc.getStartTime(), orgLoc.getEndTime())) { Organization org = organizationService.getById(organizationLocation.getOrganizationId()); - String organizationName = org != null ? org.getName() : "未知科室"; + String organizationName = org != null && org.getName() != null ? org.getName() : "未知科室"; return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime() + CommonConstants.Common.DASH + orgLoc.getEndTime() + "与" + organizationName + "时间冲突"); } diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java index d8dec26aa..7cbe989cc 100755 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java @@ -36,6 +36,6 @@ public interface IOrganizationLocationService extends IService getOrgLocListByOrgIdAndActivityDefinitionId(Long activityDefinitionId); + List getOrgLocListByOrgIdAndActivityDefinitionId(Long organizationId, Long activityDefinitionId); } \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java index c9e680fae..0212232e1 100755 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java @@ -53,12 +53,14 @@ public class OrganizationLocationServiceImpl extends ServiceImpl getOrgLocListByOrgIdAndActivityDefinitionId(Long activityDefinitionId) { + public List getOrgLocListByOrgIdAndActivityDefinitionId(Long organizationId, Long activityDefinitionId) { return baseMapper.selectList(new LambdaQueryWrapper() + .eq(OrganizationLocation::getOrganizationId, organizationId) .eq(OrganizationLocation::getActivityDefinitionId, activityDefinitionId)); }