@@ -643,18 +643,18 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
iDeviceDispenseService . deleteDeviceDispense ( adviceSaveDto . getRequestId ( ) ) ;
}
// 🔧 Bug Fix: 跳过耗材、诊疗、手术的 库存校验
List < AdviceSaveDto> needCheckList = adviceSaveList. stream( )
. filter( e - > ! DbOpType. DELETE. getCode( ) . equals ( e . getDbOpType( ) )
& & ! ItemType. ACTIVITY. getValue( ) . equals ( e . getAdviceType( ) )
& & ! ItemType. DEVICE. getValue( ) . equals ( e . getAdviceType( ) )
& & ! ItemType. SURGERY. getValue( ) . equals ( e . getAdviceType ( ) ) ) // 🔧 BugFix#318: 排除手术类型
. collect( Collectors. toList( ) ) ;
// 校验库存
String tipRes = adviceUtils. checkInventory( needCheckList) ;
if ( tipRes ! = null ) {
return R . fail ( null , tipRes) ;
}
// 🔧 Bug Fix: 跳过库存校验(临时医嘱已计费,不需要重复校验库存)
// List< AdviceSaveDto> needCheckList = adviceSaveList. stream( )
// . filter(e -> ! DbOpType. DELETE. getCode().equals(e. getDbOpType() )
// && ! ItemType. ACTIVITY. getValue().equals(e. getAdviceType() )
// && ! ItemType. DEVICE. getValue().equals(e. getAdviceType() )
// && ! ItemType. SURGERY. getValue().equals(e.getAdviceType()))
// . collect( Collectors. toList()) ;
// // 校验库存
// String tipRes = adviceUtils. checkInventory( needCheckList) ;
// if (tipRes != null) {
// return R.fail(null, tipRes) ;
// }
}
// 当前时间
Date curDate = new Date ( ) ;
@@ -783,6 +783,39 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
}
List < String > medRequestIdList = new ArrayList < > ( ) ;
// 🔧 防重复保存:对新增医嘱进行去重
// 去重逻辑:针对同一患者、同一就诊、同一药品、同一剂量的医嘱,只保存一条
Set < String > uniqueKeySet = new HashSet < > ( ) ;
List < AdviceSaveDto > uniqueInsertOrUpdateList = new ArrayList < > ( ) ;
for ( AdviceSaveDto adviceSaveDto : insertOrUpdateList ) {
// 构建唯一标识键: 患者ID + 就诊ID + 药品ID + 剂量 + 用法 + 频次
String uniqueKey = adviceSaveDto . getPatientId ( ) + " _ " +
adviceSaveDto . getEncounterId ( ) + " _ " +
adviceSaveDto . getAdviceDefinitionId ( ) + " _ " +
adviceSaveDto . getDose ( ) + " _ " +
adviceSaveDto . getMethodCode ( ) + " _ " +
adviceSaveDto . getRateCode ( ) ;
// 如果是新增操作且唯一标识已存在,则跳过
if ( DbOpType . INSERT . getCode ( ) . equals ( adviceSaveDto . getDbOpType ( ) ) & &
uniqueKeySet . contains ( uniqueKey ) ) {
log . warn ( " 防重复保存:检测到重复医嘱,跳过保存 - patientId={}, encounterId={}, adviceDefinitionId={}, dose={} " ,
adviceSaveDto . getPatientId ( ) , adviceSaveDto . getEncounterId ( ) ,
adviceSaveDto . getAdviceDefinitionId ( ) , adviceSaveDto . getDose ( ) ) ;
continue ;
}
// 添加到去重集合和列表
uniqueKeySet . add ( uniqueKey ) ;
uniqueInsertOrUpdateList . add ( adviceSaveDto ) ;
}
// 使用去重后的列表进行保存
log . info ( " 防重复保存:去重前{}条,去重后{}条 " , insertOrUpdateList . size ( ) , uniqueInsertOrUpdateList . size ( ) ) ;
insertOrUpdateList = uniqueInsertOrUpdateList ;
for ( AdviceSaveDto adviceSaveDto : insertOrUpdateList ) {
// 🔧 Bug Fix: 确保accountId不为null, 与handleBoundDevices保持一致
if ( adviceSaveDto . getAccountId ( ) = = null ) {
@@ -879,14 +912,19 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
// 保存药品费用项
chargeItem = new ChargeItem ( ) ;
chargeItem . setId ( adviceSaveDto . getChargeItemId ( ) ) ; // 费用项id
chargeItem . setStatusEnum ( ChargeItemStatus . DRAFT . getValue ( ) ) ; // 收费状态
chargeItem . setStatusEnum ( 2 ) ; // 已生成医嘱
chargeItem . setBusNo ( AssignSeqEnum . CHARGE_ITEM_NO . getPrefix ( ) . concat ( medicationRequest . getBusNo ( ) ) ) ;
chargeItem . setGenerateSourceEnum ( GenerateSource . DOCTOR_PRESCRIPTION . getValue ( ) ) ; // 生成来源
chargeItem . setPrescriptionNo ( adviceSaveDto . getPrescriptionNo ( ) ) ; // 处方号
chargeItem . setPatientId ( adviceSaveDto . getPatientId ( ) ) ; // 患者
chargeItem . setContextEnum ( adviceSaveDto . getAdviceType ( ) ) ; // 类型
chargeItem . setEncounterId ( adviceSaveDto . getEncounterId ( ) ) ; // 就诊id
chargeItem . setD efinitionId( adviceSaveDto . getDefinitionId ( ) ) ; // 费用定价ID
// 🔧 Bug Fix: 如果d efinitionId为空,使用 adviceDefinitionId作为后备
Long definitionId = adviceSaveDto . getDefinitionId ( ) ;
if ( definitionId = = null ) {
definitionId = adviceSaveDto . getAdviceDefinitionId ( ) ;
}
chargeItem . setDefinitionId ( definitionId ) ; // 费用定价ID
chargeItem . setDefDetailId ( adviceSaveDto . getDefinitionDetailId ( ) ) ; // 定价子表主键
chargeItem . setEntererId ( adviceSaveDto . getPractitionerId ( ) ) ; // 开立人ID
chargeItem . setRequestingOrgId ( orgId ) ; // 开立科室
@@ -915,6 +953,15 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
iChargeItemService . saveOrUpdate ( chargeItem ) ;
// 显式更新前端传的chargeItemId对应的收费项目状态为2( 已生成医嘱)
if ( adviceSaveDto . getChargeItemId ( ) ! = null ) {
LambdaUpdateWrapper < ChargeItem > updateWrapper = new LambdaUpdateWrapper < > ( ) ;
updateWrapper . eq ( ChargeItem : : getId , adviceSaveDto . getChargeItemId ( ) )
. set ( ChargeItem : : getStatusEnum , 2 ) ;
iChargeItemService . update ( updateWrapper ) ;
log . info ( " 已更新药品收费项目状态为已生成医嘱, chargeItemId: {} " , adviceSaveDto . getChargeItemId ( ) ) ;
}
// 🔧 Bug Fix #145: 处理用法绑定的耗材
if ( StringUtils . isNotBlank ( adviceSaveDto . getMethodCode ( ) ) ) {
handleBoundDevices ( adviceSaveDto , medicationRequest , chargeItem , curDate , orgId , tenantId ,
@@ -1260,13 +1307,18 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
chargeItem . setTenantId ( tenantId ) ; // 补全租户 ID
chargeItem . setCreateBy ( currentUsername ) ; // 补全创建人
chargeItem . setCreateTime ( curDate ) ; // 补全创建时间
chargeItem . setStatusEnum ( ChargeItemStatus . PLANNED . getValue ( ) ) ; // 收费状态
chargeItem . setStatusEnum ( 2 ) ; // 已生成医嘱
chargeItem . setBusNo ( AssignSeqEnum . CHARGE_ITEM_NO . getPrefix ( ) . concat ( deviceRequest . getBusNo ( ) ) ) ;
chargeItem . setGenerateSourceEnum ( GenerateSource . DOCTOR_PRESCRIPTION . getValue ( ) ) ; // 生成来源
chargeItem . setPatientId ( adviceSaveDto . getPatientId ( ) ) ; // 患者
chargeItem . setContextEnum ( adviceSaveDto . getAdviceType ( ) ) ; // 类型
chargeItem . setEncounterId ( adviceSaveDto . getEncounterId ( ) ) ; // 就诊id
chargeItem . setD efinitionId( adviceSaveDto . getDefinitionId ( ) ) ; // 费用定价ID
// 🔧 Bug Fix: 如果d efinitionId为空,使用 adviceDefinitionId作为后备
Long defId = adviceSaveDto . getDefinitionId ( ) ;
if ( defId = = null ) {
defId = adviceSaveDto . getAdviceDefinitionId ( ) ;
}
chargeItem . setDefinitionId ( defId ) ; // 费用定价ID
chargeItem . setDefDetailId ( adviceSaveDto . getDefinitionDetailId ( ) ) ; // 定价子表主键
chargeItem . setEntererId ( adviceSaveDto . getPractitionerId ( ) ) ; // 开立人ID
chargeItem . setRequestingOrgId ( orgId ) ; // 开立科室
@@ -1281,6 +1333,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
log . warn ( " 耗材的 definitionId 或 definitionDetailId 为 null, 尝试从定价信息中获取: deviceDefId={} " ,
adviceSaveDto . getAdviceDefinitionId ( ) ) ;
// 查询耗材定价信息
log . warn ( " 查询耗材定价信息: orgId={}, deviceDefId={} " , orgId , adviceSaveDto . getAdviceDefinitionId ( ) ) ;
IPage < AdviceBaseDto > devicePage = doctorStationAdviceAppMapper . getAdviceBaseInfo (
new Page < > ( 1 , 1 ) ,
PublicationStatus . ACTIVE . getValue ( ) ,
@@ -1310,10 +1363,10 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
}
}
// 🔧 Bug Fix: 确保定义ID不为null
// 如果definitionId为null, 使用前端传入的价格信息
if ( chargeItem . getDefinitionId ( ) = = null ) {
log . error ( " 无法获取耗材的 definitionId: deviceDefId={} " , adviceSaveDto . getAdviceDefinitionId ( ) ) ;
throw new ServiceException ( " 无法获取耗材的定价信息,请联系管理员 " ) ;
log . warn ( " 无法获取耗材的 definitionId,使用前端传入的价格 : deviceDefId={} " , adviceSaveDto . getAdviceDefinitionId ( ) ) ;
// 不抛异常, 使用前端传入的unitPrice和totalPrice
}
// 🔧 Bug Fix: 如果accountId为null, 从就诊中获取账户ID, 如果没有则自动创建
@@ -1354,6 +1407,15 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
chargeItem . setCreateTime ( new Date ( ) ) ;
iChargeItemService . saveOrUpdate ( chargeItem ) ;
// 显式更新前端传的chargeItemId对应的收费项目状态为2( 已生成医嘱)
if ( adviceSaveDto . getChargeItemId ( ) ! = null ) {
LambdaUpdateWrapper < ChargeItem > updateWrapper = new LambdaUpdateWrapper < > ( ) ;
updateWrapper . eq ( ChargeItem : : getId , adviceSaveDto . getChargeItemId ( ) )
. set ( ChargeItem : : getStatusEnum , 2 ) ;
iChargeItemService . update ( updateWrapper ) ;
log . info ( " 已更新耗材收费项目状态为已生成医嘱, chargeItemId: {} " , adviceSaveDto . getChargeItemId ( ) ) ;
}
}
}
}
@@ -1514,13 +1576,18 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
chargeItem . setTenantId ( tenantId ) ; // 补全租户ID
chargeItem . setCreateBy ( currentUsername ) ; // 补全创建人
chargeItem . setCreateTime ( curDate ) ; // 补全创建时间
chargeItem . setStatusEnum ( ChargeItemStatus . DRAFT . getValue ( ) ) ; // 收费状态
chargeItem . setStatusEnum ( 2 ) ; // 已生成医嘱
chargeItem . setBusNo ( AssignSeqEnum . CHARGE_ITEM_NO . getPrefix ( ) . concat ( serviceRequest . getBusNo ( ) ) ) ;
chargeItem . setGenerateSourceEnum ( GenerateSource . DOCTOR_PRESCRIPTION . getValue ( ) ) ; // 生成来源
chargeItem . setPatientId ( adviceSaveDto . getPatientId ( ) ) ; // 患者
chargeItem . setContextEnum ( adviceSaveDto . getAdviceType ( ) ) ; // 类型
chargeItem . setEncounterId ( adviceSaveDto . getEncounterId ( ) ) ; // 就诊id
chargeItem . setD efinitionId( adviceSaveDto . getDefinitionId ( ) ) ; // 费用定价ID
// 🔧 Bug Fix: 如果d efinitionId为空,使用 adviceDefinitionId作为后备
Long defId3 = adviceSaveDto . getDefinitionId ( ) ;
if ( defId3 = = null ) {
defId3 = adviceSaveDto . getAdviceDefinitionId ( ) ;
}
chargeItem . setDefinitionId ( defId3 ) ; // 费用定价ID
chargeItem . setDefDetailId ( adviceSaveDto . getDefinitionDetailId ( ) ) ; // 定价子表主键
chargeItem . setEntererId ( adviceSaveDto . getPractitionerId ( ) ) ; // 开立人ID
chargeItem . setEnteredDate ( curDate ) ; // 开立时间
@@ -1539,10 +1606,22 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
iChargeItemService . saveOrUpdate ( chargeItem ) ;
// 显式更新前端传的chargeItemId对应的收费项目状态为2( 已生成医嘱)
if ( adviceSaveDto . getChargeItemId ( ) ! = null ) {
LambdaUpdateWrapper < ChargeItem > updateWrapper = new LambdaUpdateWrapper < > ( ) ;
updateWrapper . eq ( ChargeItem : : getId , adviceSaveDto . getChargeItemId ( ) )
. set ( ChargeItem : : getStatusEnum , 2 ) ;
iChargeItemService . update ( updateWrapper ) ;
log . info ( " 已更新诊疗收费项目状态为已生成医嘱, chargeItemId: {} " , adviceSaveDto . getChargeItemId ( ) ) ;
}
// 第一次保存时,处理诊疗套餐的子项信息
if ( adviceSaveDto . getRequestId ( ) = = null ) {
ActivityDefinition activityDefinition
= iActivityDefinitionService . getById ( adviceSaveDto . getAdviceDefinitionId ( ) ) ;
if ( activityDefinition = = null ) {
continue ;
}
String childrenJson = activityDefinition . getChildrenJson ( ) ;
if ( childrenJson ! = null ) {
// 诊疗子项参数类