@@ -1,33 +1,53 @@
package com.openhis.web.clinicalmanage.appservice.impl ;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper ;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper ;
import com.baomidou.mybatisplus.core.metadata.IPage ;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page ;
import com.core.common.core.domain.R ;
import com.core.common.core.domain.entity.SysUser ;
import com.core.common.utils.MessageUtils ;
import com.core.common.utils.SecurityUtils ;
import com.core.system.service.ISysUserService ;
import com.openhis.administration.domain.ChargeItem ;
import com.openhis.administration.domain.Encounter ;
import com.openhis.administration.domain.OperatingRoom ;
import com.openhis.administration.domain.Organization ;
import com.openhis.administration.domain.Patient ;
import com.openhis.administration.service.IAccountService ;
import com.openhis.administration.service.IChargeItemService ;
import com.openhis.administration.service.IEncounterService ;
import com.openhis.administration.service.IOrganizationService ;
import com.openhis.administration.service.IOperatingRoomService ;
import com.openhis.administration.service.IPatientService ;
import com.openhis.common.constant.PromptMsgConstant ;
import com.openhis.clinical.domain.Surgery ;
import com.openhis.clinical.service.ISurgeryService ;
import com.openhis.common.constant.CommonConstants ;
import com.openhis.common.constant.PromptMsgConstant ;
import com.openhis.common.enums.ChargeItemStatus ;
import com.openhis.common.enums.GenerateSource ;
import com.openhis.common.enums.RequestStatus ;
import com.openhis.common.enums.TherapyTimeType ;
import com.openhis.common.utils.HisQueryUtils ;
import com.openhis.document.domain.RequestForm ;
import com.openhis.document.service.IRequestFormService ;
import com.openhis.web.clinicalmanage.appservice.ISurgeryAppService ;
import com.openhis.web.clinicalmanage.dto.SurgeryDto ;
import com.openhis.web.clinicalmanage.mapper.SurgeryAppMapper ;
import com.openhis.workflow.domain.ServiceRequest ;
import com.openhis.workflow.service.IActivityDefinitionService ;
import com.openhis.workflow.service.IServiceRequestService ;
import org.springframework.beans.BeanUtils ;
import org.springframework.stereotype.Service ;
import org.springframework.transaction.annotation.Transactional ;
import javax.annotation.Resource ;
import java.math.BigDecimal ;
import java.util.Date ;
import java.util.HashSet ;
import java.util.List ;
import static com.core.framework.datasource.DynamicDataSourceContextHolder.log ;
/**
* 手术管理应用Service业务层处理
*
* @author system
* @date 2025-12-30
*/
@Service
public class SurgeryAppServiceImpl implements ISurgeryAppService {
@@ -40,6 +60,33 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
@Resource
private IPatientService patientService ;
@Resource
private IEncounterService encounterService ;
@Resource
private IRequestFormService requestFormService ;
@Resource
private IServiceRequestService serviceRequestService ;
@Resource
private IChargeItemService chargeItemService ;
@Resource
private IActivityDefinitionService activityDefinitionService ;
@Resource
private IAccountService accountService ;
@Resource
private IOrganizationService organizationService ;
@Resource
private ISysUserService sysUserService ;
@Resource
private IOperatingRoomService operatingRoomService ;
/**
* 分页查询手术列表
*
@@ -85,6 +132,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
* @return 结果
*/
@Override
@Transactional ( rollbackFor = Exception . class )
public R < ? > addSurgery ( SurgeryDto surgeryDto ) {
// 校验患者是否存在
Patient patient = patientService . getById ( surgeryDto . getPatientId ( ) ) ;
@@ -92,14 +140,169 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
return R . fail ( " 患者信息不存在 " ) ;
}
// 校验就诊ID是否存在
if ( surgeryDto . getEncounterId ( ) = = null ) {
return R . fail ( " 请选择就诊流水号 " ) ;
}
// 校验就诊记录是否存在
Encounter encounter = encounterService . getById ( surgeryDto . getEncounterId ( ) ) ;
if ( encounter = = null ) {
return R . fail ( " 就诊记录不存在 " ) ;
}
// 获取患者的自费账户ID
Long accountId = accountService . getSelfPayAccount ( surgeryDto . getEncounterId ( ) ) ;
if ( accountId = = null ) {
return R . fail ( " 未找到患者的账户信息,请先完成挂号或住院登记 " ) ;
}
// 当前登录账号的科室id
Long orgId = SecurityUtils . getLoginUser ( ) . getOrgId ( ) ;
// 当前参与者ID
Long practitionerId = SecurityUtils . getLoginUser ( ) . getPractitionerId ( ) ;
// 当前用户ID
Long userId = SecurityUtils . getLoginUser ( ) . getUserId ( ) ;
// 当前时间
Date curDate = new Date ( ) ;
// 获取申请医生姓名(从当前登录用户信息中获取)
String applyDoctorName = SecurityUtils . getLoginUser ( ) . getUser ( ) . getNickName ( ) ;
// 获取申请科室名称
String applyDeptName = null ;
// 优先从用户信息的部门中获取
if ( SecurityUtils . getLoginUser ( ) . getUser ( ) . getDept ( ) ! = null ) {
applyDeptName = SecurityUtils . getLoginUser ( ) . getUser ( ) . getDept ( ) . getDeptName ( ) ;
}
// 如果用户信息中没有部门名称,则从机构表中查询
if ( applyDeptName = = null & & orgId ! = null ) {
Organization org = organizationService . getById ( orgId ) ;
if ( org ! = null ) {
applyDeptName = org . getName ( ) ;
}
}
// 转换为实体对象
Surgery surgery = new Surgery ( ) ;
BeanUtils . copyProperties ( surgeryDto , surgery ) ;
// 清空名称字段, 确保从ID重新查询并填充
surgery . setPatientName ( null ) ;
surgery . setMainSurgeonName ( null ) ;
surgery . setAnesthetistName ( null ) ;
surgery . setAssistant1Name ( null ) ;
surgery . setAssistant2Name ( null ) ;
surgery . setScrubNurseName ( null ) ;
surgery . setOperatingRoomName ( null ) ;
surgery . setOrgName ( null ) ;
surgery . setApplyDoctorName ( null ) ;
surgery . setApplyDeptName ( null ) ;
// 设置申请医生信息(默认使用当前登录医生)
// 注意:必须放在 copyProperties 之后,确保覆盖前端可能传递的空值
log . info ( " 设置申请医生信息 - doctorId: {}, doctorName: {}, deptId: {}, deptName: {} " ,
practitionerId , applyDoctorName , orgId , applyDeptName ) ;
log . info ( " 前端提交的数据 - applyDoctorId: {}, applyDoctorName: {}, applyDeptId: {}, applyDeptName: {} " ,
surgeryDto . getApplyDoctorId ( ) , surgeryDto . getApplyDoctorName ( ) , surgeryDto . getApplyDeptId ( ) , surgeryDto . getApplyDeptName ( ) ) ;
surgery . setApplyDoctorId ( practitionerId ) ;
surgery . setApplyDoctorName ( applyDoctorName ) ;
surgery . setApplyDeptId ( orgId ) ;
surgery . setApplyDeptName ( applyDeptName ) ;
// 填充其他人员字段的名称
fillSurgeryNameFields ( surgery ) ;
// 设置创建者ID( 因为数据库中 create_by 是 bigint 类型)
// 这个值会被 MybastisColumnsHandler 自动填充,所以这里不需要设置
log . info ( " 准备插入手术记录 - applyDoctorId: {}, applyDoctorName: {}, applyDeptId: {}, applyDeptName: {} " ,
surgery . getApplyDoctorId ( ) , surgery . getApplyDoctorName ( ) , surgery . getApplyDeptId ( ) , surgery . getApplyDeptName ( ) ) ;
log . info ( " 准备插入手术记录 - mainSurgeonId: {}, mainSurgeonName: {}, anesthetistId: {}, anesthetistName: {} " ,
surgery . getMainSurgeonId ( ) , surgery . getMainSurgeonName ( ) , surgery . getAnesthetistId ( ) , surgery . getAnesthetistName ( ) ) ;
log . info ( " 准备插入手术记录 - assistant1Id: {}, assistant1Name: {}, assistant2Id: {}, assistant2Name: {} " ,
surgery . getAssistant1Id ( ) , surgery . getAssistant1Name ( ) , surgery . getAssistant2Id ( ) , surgery . getAssistant2Name ( ) ) ;
log . info ( " 准备插入手术记录 - operatingRoomId: {}, operatingRoomName: {}, orgId: {}, orgName: {} " ,
surgery . getOperatingRoomId ( ) , surgery . getOperatingRoomName ( ) , surgery . getOrgId ( ) , surgery . getOrgName ( ) ) ;
Long surgeryId = surgeryService . insertSurgery ( surgery ) ;
log . info ( " 手术记录插入成功 - surgeryId: {}, surgeryNo: {} " , surgeryId , surgery . getSurgeryNo ( ) ) ;
// 生成处方号(医嘱号)
String prescriptionNo = surgery . getSurgeryNo ( ) ;
// 保存申请单
RequestForm requestForm = new RequestForm ( ) ;
requestForm . setTypeCode ( " SURGERY " ) ; // 申请单类型
requestForm . setPrescriptionNo ( prescriptionNo ) ; // 处方号(使用手术单号)
requestForm . setName ( " 手术申请单 " ) ; // 名称
requestForm . setEncounterId ( surgeryDto . getEncounterId ( ) ) ; // 就诊ID
requestForm . setRequesterId ( practitionerId ) ; // 申请人
requestForm . setDescJson ( buildDescJson ( surgeryDto ) ) ; // 描述内容
requestFormService . save ( requestForm ) ;
// 生成手术医嘱
ServiceRequest serviceRequest = new ServiceRequest ( ) ;
serviceRequest . setStatusEnum ( RequestStatus . DRAFT . getValue ( ) ) ;
serviceRequest . setBusNo ( String . format ( " %04d " , ( int ) ( Math . random ( ) * 10000 ) ) ) ;
serviceRequest . setGenerateSourceEnum ( GenerateSource . DOCTOR_PRESCRIPTION . getValue ( ) ) ; // 生成来源
serviceRequest . setPrescriptionNo ( prescriptionNo ) ;
serviceRequest . setTherapyEnum ( TherapyTimeType . TEMPORARY . getValue ( ) ) ; // 治疗类型
serviceRequest . setQuantity ( BigDecimal . valueOf ( 1 ) ) ; // 请求数量
serviceRequest . setUnitCode ( " 次 " ) ; // 请求单位编码
serviceRequest . setCategoryEnum ( 4 ) ; // 请求类型: 4-手术
serviceRequest . setActivityId ( surgeryId ) ; // 手术ID作为诊疗定义id
serviceRequest . setPatientId ( surgeryDto . getPatientId ( ) ) ; // 患者
serviceRequest . setRequesterId ( practitionerId ) ; // 开方医生
serviceRequest . setEncounterId ( surgeryDto . getEncounterId ( ) ) ; // 就诊id
serviceRequest . setAuthoredTime ( curDate ) ; // 请求签发时间
serviceRequest . setOrgId ( orgId ) ; // 执行科室
serviceRequestService . save ( serviceRequest ) ;
// 生成收费项目
ChargeItem chargeItem = new ChargeItem ( ) ;
chargeItem . setStatusEnum ( ChargeItemStatus . DRAFT . getValue ( ) ) ; // 收费状态
chargeItem . setBusNo ( " CI " + serviceRequest . getBusNo ( ) ) ;
chargeItem . setGenerateSourceEnum ( GenerateSource . DOCTOR_PRESCRIPTION . getValue ( ) ) ; // 生成来源
chargeItem . setPatientId ( surgeryDto . getPatientId ( ) ) ; // 患者
chargeItem . setContextEnum ( 3 ) ; // 类型: 3-诊疗
chargeItem . setEncounterId ( surgeryDto . getEncounterId ( ) ) ; // 就诊id
chargeItem . setAccountId ( accountId ) ; // 账户ID
chargeItem . setDefinitionId ( surgeryId ) ; // 手术ID作为费用定价ID
chargeItem . setEntererId ( practitionerId ) ; // 开立人ID
chargeItem . setEnteredDate ( curDate ) ; // 开立时间
chargeItem . setServiceTable ( CommonConstants . TableName . WOR_SERVICE_REQUEST ) ; // 医疗服务类型
chargeItem . setServiceId ( serviceRequest . getId ( ) ) ; // 医疗服务ID
chargeItem . setProductTable ( " cli_surgery " ) ; // 手术表
chargeItem . setProductId ( surgeryId ) ; // 手术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 ) ;
return R . ok ( surgeryId , MessageUtils . createMessage ( PromptMsgConstant . Common . M00001 , new Object [ ] { " 手术信息 " } ) ) ;
}
/**
* 构建描述JSON
*
* @param surgeryDto 手术信息
* @return JSON字符串
*/
private String buildDescJson ( SurgeryDto surgeryDto ) {
return String . format (
" { \" surgeryName \" : \" %s \" , \" surgeryLevel \" : \" %s \" , \" surgeryIndication \" : \" %s \" , \" preoperativeDiagnosis \" : \" %s \" } " ,
surgeryDto . getSurgeryName ( ) ! = null ? surgeryDto . getSurgeryName ( ) : " " ,
surgeryDto . getSurgeryLevel ( ) ! = null ? surgeryDto . getSurgeryLevel ( ) : " " ,
surgeryDto . getSurgeryIndication ( ) ! = null ? surgeryDto . getSurgeryIndication ( ) : " " ,
surgeryDto . getPreoperativeDiagnosis ( ) ! = null ? surgeryDto . getPreoperativeDiagnosis ( ) : " "
) ;
}
/**
* 修改手术信息
*
@@ -117,7 +320,22 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
// 转换为实体对象
Surgery surgery = new Surgery ( ) ;
BeanUtils . copyProperties ( surgeryDto , surgery ) ;
// 先清空名称字段,确保重新填充
surgery . setPatientName ( null ) ;
surgery . setMainSurgeonName ( null ) ;
surgery . setAnesthetistName ( null ) ;
surgery . setAssistant1Name ( null ) ;
surgery . setAssistant2Name ( null ) ;
surgery . setScrubNurseName ( null ) ;
surgery . setOperatingRoomName ( null ) ;
surgery . setOrgName ( null ) ;
surgery . setApplyDoctorName ( null ) ;
surgery . setApplyDeptName ( null ) ;
// 填充其他人员字段的名称
fillSurgeryNameFields ( surgery ) ;
surgeryService . updateSurgery ( surgery ) ;
return R . ok ( null , MessageUtils . createMessage ( PromptMsgConstant . Common . M00002 , new Object [ ] { " 手术信息 " } ) ) ;
}
@@ -163,4 +381,124 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService {
surgeryService . updateSurgeryStatus ( id , statusEnum ) ;
return R . ok ( null , MessageUtils . createMessage ( PromptMsgConstant . Common . M00004 , new Object [ ] { " 手术状态 " } ) ) ;
}
}
/**
* 根据患者ID查询就诊列表
*
* @param patientId 患者ID
* @return 就诊列表
*/
@Override
public R < List < Encounter > > getEncounterListByPatientId ( Long patientId ) {
if ( patientId = = null ) {
return R . fail ( " 患者ID不能为空 " ) ;
}
// 查询该患者的所有就诊记录(进行中的优先)
QueryWrapper < Encounter > wrapper = new QueryWrapper < > ( ) ;
wrapper . eq ( " patient_id " , patientId )
. in ( " status_enum " , 2 , 3 ) // 2-进行中, 3-已完成
. orderByAsc ( " CASE WHEN status_enum = 2 THEN 0 ELSE 1 END " ) // 进行中的排在前面
. orderByDesc ( " start_time " ) ; // 按开始时间倒序
List < Encounter > encounterList = encounterService . list ( wrapper ) ;
if ( encounterList = = null | | encounterList . isEmpty ( ) ) {
return R . fail ( " 该患者暂无就诊记录,请先挂号或办理住院 " ) ;
}
return R . ok ( encounterList ) ;
}
/**
* 填充手术记录中的名称字段
* 根据ID反向查询用户表、机构表、手术室表、患者表、就诊表,填充对应的名称字段
*
* @param surgery 手术实体对象
*/
private void fillSurgeryNameFields ( Surgery surgery ) {
// 填充患者姓名
if ( surgery . getPatientId ( ) ! = null ) {
Patient patient = patientService . getById ( surgery . getPatientId ( ) ) ;
if ( patient ! = null ) {
surgery . setPatientName ( patient . getName ( ) ) ;
}
}
// 填充主刀医生姓名
if ( surgery . getMainSurgeonId ( ) ! = null ) {
SysUser mainSurgeon = sysUserService . selectUserById ( surgery . getMainSurgeonId ( ) ) ;
if ( mainSurgeon ! = null ) {
surgery . setMainSurgeonName ( mainSurgeon . getNickName ( ) ) ;
}
}
// 填充麻醉医生姓名
if ( surgery . getAnesthetistId ( ) ! = null ) {
SysUser anesthetist = sysUserService . selectUserById ( surgery . getAnesthetistId ( ) ) ;
if ( anesthetist ! = null ) {
surgery . setAnesthetistName ( anesthetist . getNickName ( ) ) ;
}
}
// 填充助手1姓名
if ( surgery . getAssistant1Id ( ) ! = null ) {
SysUser assistant1 = sysUserService . selectUserById ( surgery . getAssistant1Id ( ) ) ;
if ( assistant1 ! = null ) {
surgery . setAssistant1Name ( assistant1 . getNickName ( ) ) ;
}
}
// 填充助手2姓名
if ( surgery . getAssistant2Id ( ) ! = null ) {
SysUser assistant2 = sysUserService . selectUserById ( surgery . getAssistant2Id ( ) ) ;
if ( assistant2 ! = null ) {
surgery . setAssistant2Name ( assistant2 . getNickName ( ) ) ;
}
}
// 填充巡回护士姓名
if ( surgery . getScrubNurseId ( ) ! = null ) {
SysUser scrubNurse = sysUserService . selectUserById ( surgery . getScrubNurseId ( ) ) ;
if ( scrubNurse ! = null ) {
surgery . setScrubNurseName ( scrubNurse . getNickName ( ) ) ;
}
}
// 填充手术室名称
if ( surgery . getOperatingRoomId ( ) ! = null ) {
OperatingRoom operatingRoom = operatingRoomService . getById ( surgery . getOperatingRoomId ( ) ) ;
if ( operatingRoom ! = null ) {
surgery . setOperatingRoomName ( operatingRoom . getName ( ) ) ;
}
}
// 填充执行科室名称
if ( surgery . getOrgId ( ) ! = null ) {
Organization org = organizationService . getById ( surgery . getOrgId ( ) ) ;
if ( org ! = null ) {
surgery . setOrgName ( org . getName ( ) ) ;
}
}
// 填充申请科室名称(如果还没有设置)
if ( surgery . getApplyDeptId ( ) ! = null & & ( surgery . getApplyDeptName ( ) = = null | | surgery . getApplyDeptName ( ) . isEmpty ( ) ) ) {
Organization applyDept = organizationService . getById ( surgery . getApplyDeptId ( ) ) ;
if ( applyDept ! = null ) {
surgery . setApplyDeptName ( applyDept . getName ( ) ) ;
}
}
// 填充申请医生姓名(如果还没有设置)
if ( surgery . getApplyDoctorId ( ) ! = null & & ( surgery . getApplyDoctorName ( ) = = null | | surgery . getApplyDoctorName ( ) . isEmpty ( ) ) ) {
SysUser applyDoctor = sysUserService . selectUserById ( surgery . getApplyDoctorId ( ) ) ;
if ( applyDoctor ! = null ) {
surgery . setApplyDoctorName ( applyDoctor . getNickName ( ) ) ;
}
}
log . info ( " 填充手术名称字段完成 - patientName: {}, mainSurgeonName: {}, anesthetistName: {}, assistant1Name: {}, assistant2Name: {}, scrubNurseName: {}, operatingRoomName: {}, orgName: {} " ,
surgery . getPatientName ( ) , surgery . getMainSurgeonName ( ) , surgery . getAnesthetistName ( ) , surgery . getAssistant1Name ( ) ,
surgery . getAssistant2Name ( ) , surgery . getScrubNurseName ( ) , surgery . getOperatingRoomName ( ) , surgery . getOrgName ( ) ) ;
}
}