fix: Bug #407 #385 检查申请医嘱分类错误及预结算账户验证修复

主要修复:
  - 检查申请医嘱类型正确设置为诊疗(3),避免被错误归类为药品
  - 检查申请收费项获取真实自费账户,预结算验证accountId必须有效存在
  - 签发时补充诊疗费用项诊断关联信息变更模块:
  - ExamApplyController:使用ItemType枚举,获取真实账户替代占位值0
-DoctorStationAdviceAppService:按枚举标准分类医嘱,验证accountId有效性
  - IChargeBillService:productId=0时从ServiceRequest.contentJson获取项目名称
  - PaymentRecService:预结算自动修复账户不存在的历史数据
  - Mapper:排除衍生执行记录,productId=0时补充查询逻辑
  - ServiceRequest实体:activityId字段添加ALWAYS插入策略
This commit is contained in:
wangjian963
2026-04-23 17:17:04 +08:00
parent 2a8e662b44
commit 95e379e5a5
7 changed files with 293 additions and 47 deletions

View File

@@ -41,7 +41,9 @@ import com.openhis.web.paymentmanage.appservice.IChargeBillService;
import com.openhis.web.paymentmanage.dto.*;
import com.openhis.web.paymentmanage.mapper.ChargeBillMapper;
import com.openhis.workflow.domain.ActivityDefinition;
import com.openhis.workflow.domain.ServiceRequest;
import com.openhis.workflow.service.IActivityDefinitionService;
import com.openhis.workflow.service.IServiceRequestService;
import com.openhis.yb.domain.ClinicSettle;
import com.openhis.yb.domain.ClinicUnSettle;
import com.openhis.yb.domain.InfoPerson;
@@ -111,6 +113,8 @@ public class IChargeBillServiceImpl implements IChargeBillService {
@Autowired
private IActivityDefinitionService iActivityDefinitionService;
@Autowired
private IServiceRequestService iServiceRequestService;
@Autowired
private IPractitionerService iPractitionerService;
@Autowired
private IHealthcareServiceService iHealthcareServiceService;
@@ -265,10 +269,31 @@ public class IChargeBillServiceImpl implements IChargeBillService {
.setTotalPrice(chargeItem.getTotalPrice()).setQuantityUnit(chargeItem.getQuantityUnit())
.setTotalVolume(device.getSize()).setQuantityValue(chargeItem.getQuantityValue());
} else if (CommonConstants.TableName.WOR_ACTIVITY_DEFINITION.equals(chargeItem.getProductTable())) {
ActivityDefinition activity = iActivityDefinitionService.getById(chargeItem.getProductId());
chargeItemDetailVO.setDirClass(activity.getChrgitmLv() + "").setChargeItemName(activity.getName())
.setTotalPrice(chargeItem.getTotalPrice()).setQuantityUnit(chargeItem.getQuantityUnit())
.setTotalVolume("").setQuantityValue(chargeItem.getQuantityValue());
// 🔧 BugFix#385: 检查申请创建的收费项 productId=0需从 ServiceRequest.contentJson 获取项目名称
if (chargeItem.getProductId() != null && chargeItem.getProductId() > 0) {
ActivityDefinition activity = iActivityDefinitionService.getById(chargeItem.getProductId());
chargeItemDetailVO.setDirClass(activity.getChrgitmLv() + "").setChargeItemName(activity.getName())
.setTotalPrice(chargeItem.getTotalPrice()).setQuantityUnit(chargeItem.getQuantityUnit())
.setTotalVolume("").setQuantityValue(chargeItem.getQuantityValue());
} else {
// productId=0 时,从关联的 ServiceRequest 获取项目名称
ServiceRequest serviceRequest = iServiceRequestService.getById(chargeItem.getServiceId());
String itemName = "未知项目";
String dirClass = "3"; // 默认诊疗类
if (serviceRequest != null && serviceRequest.getContentJson() != null) {
try {
JSONObject json = JSON.parseObject(serviceRequest.getContentJson());
if (json.containsKey("adviceName")) {
itemName = json.getString("adviceName");
}
} catch (Exception e) {
log.warn("解析ServiceRequest.contentJson失败: {}", e.getMessage());
}
}
chargeItemDetailVO.setDirClass(dirClass).setChargeItemName(itemName)
.setTotalPrice(chargeItem.getTotalPrice()).setQuantityUnit(chargeItem.getQuantityUnit())
.setTotalVolume("").setQuantityValue(chargeItem.getQuantityValue());
}
} else {
HealthcareService healthcareService = iHealthcareServiceService.getById(chargeItem.getServiceId());
chargeItemDetailVO.setDirClass("3").setChargeItemName(healthcareService.getName())
@@ -347,7 +372,19 @@ public class IChargeBillServiceImpl implements IChargeBillService {
Long definitionId = chargeItem.getDefinitionId();
ChargeItemDefinition chargeItemDefinition = iChargeItemDefinitionService.getById(definitionId);
// 🔧 BugFix#385: 检查申请创建的收费项 definition_id=0chargeItemDefinition 会为 null
ChargeItemDefinition chargeItemDefinition = null;
if (definitionId != null && definitionId > 0) {
chargeItemDefinition = iChargeItemDefinitionService.getById(definitionId);
}
// 当 definitionId=0 或 chargeItemDefinition 为 null 时,跳过医保分类统计
// 检查类项目默认归类为"检查费"
if (chargeItemDefinition == null) {
// 检查申请的收费项归类为检查费03
sum03 = sum03.add(chargeItem.getTotalPrice());
continue;
}
YbMedChrgItmType medChrgItmType
= YbMedChrgItmType.getByCode(Integer.parseInt(chargeItemDefinition.getYbType()));

View File

@@ -6,6 +6,7 @@ package com.openhis.web.paymentmanage.appservice.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
@@ -241,14 +242,21 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
.collect(Collectors.toList());
// account去重
List<Long> distinctAccountIdList = accountIdList.stream().distinct().collect(Collectors.toList());
// 检查是否存在accountId为null的收费项
// 检查是否存在accountId为null或0的收费项
long nullAccountIdCount = chargeItemList.stream()
.map(ChargeItem::getAccountId)
.filter(Objects::isNull)
.count();
long zeroAccountIdCount = chargeItemList.stream()
.map(ChargeItem::getAccountId)
.filter(id -> id != null && id == 0L)
.count();
if (nullAccountIdCount > 0) {
throw new ServiceException("部分收费项缺少账户信息,请检查收费项数据");
}
if (zeroAccountIdCount > 0) {
throw new ServiceException("部分收费项账户ID为0无效请检查收费项数据或重新创建检查申请");
}
if (distinctAccountIdList.isEmpty()) {
throw new ServiceException("未找到有效的账户信息");
}
@@ -257,15 +265,66 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
// 在挂号费等场景下可能因数据不一致导致查不到,引发误报
List<Account> accountList = iAccountService.list(new LambdaQueryWrapper<Account>()
.in(Account::getId, distinctAccountIdList));
// 🔧 Bug Fix: 处理账户不存在的情况(历史数据修复)
if (accountList.size() != distinctAccountIdList.size()) {
// 部分账户查不到时,记录警告日志,并校验是否每个收费项都能找到对应账户
Set<Long> foundAccountIds = accountList.stream().map(Account::getId).collect(Collectors.toSet());
List<Long> missingAccountIds = distinctAccountIdList.stream()
.filter(id -> !foundAccountIds.contains(id)).collect(Collectors.toList());
if (accountList.isEmpty()) {
throw new ServiceException("未查询到任何账户信息encounterId" + prePaymentDto.getEncounterId()
+ "期望accountId列表" + distinctAccountIdList);
logger.warn("预结算发现部分账户不存在missingAccountIds={}将自动修复收费项的accountId",
missingAccountIds);
// 获取或创建有效的自费账户
Account selfAccount = iAccountService.getSelfAccount(prePaymentDto.getEncounterId());
if (selfAccount == null) {
// 自动创建自费账户
Account newAccount = new Account();
newAccount.setPatientId(chargeItemList.get(0).getPatientId());
newAccount.setEncounterId(prePaymentDto.getEncounterId());
newAccount.setContractNo(CommonConstants.BusinessName.DEFAULT_CONTRACT_NO);
newAccount.setTypeCode(AccountType.PERSONAL_CASH_ACCOUNT.getCode());
newAccount.setBalanceAmount(BigDecimal.ZERO);
newAccount.setStatusEnum(AccountStatus.ACTIVE.getValue());
newAccount.setEncounterFlag(Whether.YES.getValue());
newAccount.setName(AccountType.PERSONAL_CASH_ACCOUNT.getInfo());
Long newAccountId = iAccountService.saveAccountByRegister(newAccount);
selfAccount = iAccountService.getById(newAccountId);
logger.info("预结算自动创建自费账户newAccountId={}", newAccountId);
}
// 修复收费项的 accountId
for (Long missingAccountId : missingAccountIds) {
// 找到使用该无效 accountId 的收费项
List<ChargeItem> affectedChargeItems = chargeItemList.stream()
.filter(ci -> ci.getAccountId() != null && ci.getAccountId().equals(missingAccountId))
.collect(Collectors.toList());
for (ChargeItem ci : affectedChargeItems) {
LambdaUpdateWrapper<ChargeItem> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ChargeItem::getId, ci.getId())
.set(ChargeItem::getAccountId, selfAccount.getId());
iChargeItemService.update(updateWrapper);
logger.info("预结算修复收费项accountIdchargeItemId={}oldAccountId={}newAccountId={}",
ci.getId(), missingAccountId, selfAccount.getId());
// 更新本地对象的 accountId以便后续处理使用正确的值
ci.setAccountId(selfAccount.getId());
}
}
// 重新查询账户列表
accountList = iAccountService.list(new LambdaQueryWrapper<Account>()
.eq(Account::getId, selfAccount.getId()));
// 重新构建 accountIdList已修复
distinctAccountIdList = chargeItemList.stream()
.map(ChargeItem::getAccountId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
logger.info("预结算账户修复完成最终使用accountId={}", selfAccount.getId());
}
// 账户id对应的账单列表