@@ -1,6 +1,7 @@
package com.openhis.financial.service.impl ;
import java.math.BigDecimal ;
import java.math.RoundingMode ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
@@ -16,25 +17,41 @@ import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper ;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper ;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl ;
import com.core.common.exception.ServiceException ;
import com.core.common.utils.AssignSeqUtil ;
import com.core.common.utils.SecurityUtils ;
import com.core.common.utils.StringUtils ;
import com.openhis.administration.domain.ChargeItemDefinition ;
import com.openhis.administration.domain.DeviceDefinition ;
import com.openhis.administration.domain.HealthcareService ;
import com.openhis.administration.service.IChargeItemDefinitionService ;
import com.openhis.administration.service.IChargeItemService ;
import com.openhis.administration.service.IDeviceDefinitionService ;
import com.openhis.administration.service.IHealthcareServiceService ;
import com.openhis.administration.service.impl.PatientServiceImpl ;
import com.openhis.administration.service.impl.PatientStudentServiceImpl ;
import com.openhis.common.constant.CommonConstants ;
import com.openhis.common.constant.YbCommonConstants ;
import com.openhis.common.enums.DelFlag ;
import com.openhis.common.enums.ItemType ;
import com.openhis.common.enums.PaymentKind ;
import com.openhis.common.enums.PaymentStatus ;
import com.openhis.common.enums.ybenums.YbChrgitmLv ;
import com.openhis.common.enums.ybenums.YbMdtrtCertType ;
import com.openhis.common.enums.ybenums.YbMedChrgItmType ;
import com.openhis.common.enums.ybenums.YbMedType ;
import com.openhis.financial.domain.Contract ;
import com.openhis.financial.domain.PaymentReconciliation ;
import com.openhis.financial.mapper.PaymentReconciliationMapper ;
import com.openhis.financial.model.PaymentReconciliationAccountDel ;
import com.openhis.financial.model.PaymentResult ;
import com.openhis.financial.model.PaymentedItemModel ;
import com.openhis.financial.model.PrePaymentResult ;
import com.openhis.financial.model.* ;
import com.openhis.financial.service.IContractService ;
import com.openhis.financial.service.IPaymentReconciliationService ;
import com.openhis.medication.domain.MedicationDefinition ;
import com.openhis.medication.service.IMedicationDefinitionService ;
import com.openhis.nenu.dto.GfTypeRatioDto ;
import com.openhis.nenu.service.impl.GfRatioServiceImpl ;
import com.openhis.workflow.domain.ActivityDefinition ;
import com.openhis.workflow.service.IActivityDefinitionService ;
import com.openhis.yb.dto.Clinic2206OrderOutput ;
import com.openhis.yb.dto.ClinicReg2201Output ;
import com.openhis.yb.dto.PaymentInpatientDto ;
@@ -57,6 +74,24 @@ public class PaymentReconciliationServiceImpl extends ServiceImpl<PaymentReconci
private IContractService iContractService ;
@Autowired
private YbManager ybManager ;
@Autowired
private GfRatioServiceImpl gfRatioService ;
@Autowired
private PatientServiceImpl patientService ;
@Autowired
private PatientStudentServiceImpl patientStudentService ;
@Autowired
private IChargeItemService chargeItemService ;
@Autowired
private IChargeItemDefinitionService chargeItemDefinitionService ;
@Autowired
private IDeviceDefinitionService deviceDefinitionService ;
@Autowired
private IActivityDefinitionService activityDefinitionService ;
@Autowired
private IMedicationDefinitionService medicationDefinitionService ;
@Autowired
private IHealthcareServiceService healthcareServiceService ;
/**
* 根据支付id获取对应收费项目的id列表
@@ -143,6 +178,9 @@ public class PaymentReconciliationServiceImpl extends ServiceImpl<PaymentReconci
case " 220100 " : // 长春市医保(长大)
Map < String , List < PaymentedItemModel > > collect =
paymentedItemList . stream ( ) . collect ( Collectors . groupingBy ( PaymentedItemModel : : getMedType ) ) ;
if ( collect . entrySet ( ) . size ( ) > 1 ) {
throw new ServiceException ( " 医保只接受同种医疗类型结算(普通门诊与慢病等不可以同时结算)! " ) ;
}
PrePaymentResult result ;
for ( Map . Entry < String , List < PaymentedItemModel > > medTypeKV : collect . entrySet ( ) ) {
Clinic2206OrderOutput clinic2206OrderOutput = null ;
@@ -161,19 +199,108 @@ public class PaymentReconciliationServiceImpl extends ServiceImpl<PaymentReconci
}
// 调用预结算
clinic2206OrderOutput = ybManager . preSettle ( contract , medTypeKV . getValue ( ) . get ( 0 ) . getEncounterId ( ) ,
ybMdtrtCertType , busiCardInfo , reg2201Output , " 01 " , medTypeKV . getValue ( ) . stream ( )
. map ( PaymentedItemModel : : getChargeItemId ) . collect ( Collectors . toList ( ) ) ,
ybMdtrtCertType , busiCardInfo , reg2201Output , " 01 " , medTypeKV . getValue ( ) ,
YbMedType . getByValue ( medTypeKV . getKey ( ) ) ) ;
prePaymentResult = new PrePaymentResult ( ) ;
BeanUtils . copyProperties ( clinic2206OrderOutput , prePaymentResult ) ;
}
break ;
case " STUDENT0000 " :
prePaymentResult = this . studentSelfPay ( paymentedItemList ) ;
break ;
case " STUDENT220100 " :
case " STUDENT229900 " :
case " STUDENT220199 " :
prePaymentResult = this . studentYbPay ( contract , ybMdtrtCertType , busiCardInfo , " 01 " , paymentedItemList ) ;
break ;
default :
break ;
}
return prePaymentResult ;
}
/**
* 学生二次报销
*
* @param contract 合同
* @param ybMdtrtCertType 医疗类别
* @param busiCardInfo 电子码
* @param s 按项目收费还是按病种收费( 该字段目前在系统里面没用上, 默认都是01)
* @param paymentedItemList 收费项
* @return 预结算结果
*/
private PrePaymentResult studentYbPay ( Contract contract , YbMdtrtCertType ybMdtrtCertType , String busiCardInfo ,
String s , List < PaymentedItemModel > paymentedItemList ) {
// 查比例及分类信息(PaymentedItemModel在chargeItem表中不是一定存在的所以此处改用单独查询)
List < StudentPaymentItemModel > allPaymentItemList = getStudentPaymentItemModelList ( paymentedItemList ) ;
// 拟定使用公费医疗的情况下实收金额
BigDecimal onceReceivedAmount = BigDecimal . ZERO ;
for ( StudentPaymentItemModel studentPaymentItemModel : allPaymentItemList ) {
// 获取折扣比例
BigDecimal ratio = studentPaymentItemModel . getTwiceRatio ( ) = = null ? studentPaymentItemModel . getSelfRatio ( )
: studentPaymentItemModel . getTwiceRatio ( ) ;
// 计算金额
onceReceivedAmount = onceReceivedAmount . add ( studentPaymentItemModel . getTotalPrice ( )
. multiply ( ratio . divide ( new BigDecimal ( " 100 " ) , 6 , RoundingMode . HALF_UP ) ) ) ;
}
// 医保结算
PrePaymentResult prePaymentResult =
this . studentPreSettleYb ( contract , ybMdtrtCertType , busiCardInfo , paymentedItemList ) ;
if ( prePaymentResult = = null ) {
throw new ServiceException ( " 医生开具的收费项未分配对应的医疗类型! " ) ;
}
BigDecimal psnPartAmt = prePaymentResult . getPsnPartAmt ( ) ;
if ( psnPartAmt . compareTo ( onceReceivedAmount ) > 0 ) {
prePaymentResult . setGfRatio ( psnPartAmt . subtract ( onceReceivedAmount ) ) ;
prePaymentResult . setPsnCashPay ( onceReceivedAmount ) ;
} else {
prePaymentResult . setGfRatio ( BigDecimal . ZERO ) ;
}
return prePaymentResult ;
}
/**
* 学生一次报销
*
* @param paymentedItemList 收费项
* @return 预结算结果
*/
private PrePaymentResult studentSelfPay ( List < PaymentedItemModel > paymentedItemList ) {
List < StudentPaymentItemModel > allPaymentItemList = getStudentPaymentItemModelList ( paymentedItemList ) ;
// 拟定使用公费医疗的情况下实收金额
BigDecimal onceReceivedAmount = BigDecimal . ZERO ;
for ( StudentPaymentItemModel studentPaymentItemModel : allPaymentItemList ) {
// 获取折扣比例
BigDecimal ratio = studentPaymentItemModel . getTwiceRatio ( ) = = null ? studentPaymentItemModel . getSelfRatio ( )
: studentPaymentItemModel . getTwiceRatio ( ) ;
// 计算金额
onceReceivedAmount = onceReceivedAmount . add ( studentPaymentItemModel . getTotalPrice ( ) . multiply ( ratio ) ) ;
}
PrePaymentResult prePaymentResult = new PrePaymentResult ( ) ;
BigDecimal sumAmount = BigDecimal . ZERO ;
for ( PaymentedItemModel item : paymentedItemList ) {
sumAmount = sumAmount . add ( item . getTotalPrice ( ) ) ;
}
prePaymentResult . setMedfeeSumamt ( sumAmount ) ;
prePaymentResult . setFulamtOwnpayAmt ( sumAmount ) ;
prePaymentResult . setPsnPartAmt ( sumAmount ) ;
prePaymentResult . setPsnCashPay ( onceReceivedAmount . divide ( new BigDecimal ( " 100 " ) , 6 , RoundingMode . HALF_UP ) ) ;
prePaymentResult . setGfRatio ( sumAmount . subtract ( prePaymentResult . getPsnCashPay ( ) ) ) ;
prePaymentResult . setChrgBchno ( CommonConstants . BusinessName . DEFAULT_STUDENT_CONTRACT_NO ) ;
return prePaymentResult ;
}
/**
* 【门诊结算】
*
@@ -189,7 +316,8 @@ public class PaymentReconciliationServiceImpl extends ServiceImpl<PaymentReconci
public PaymentResult settle ( Contract contract , String payTransNo , YbMdtrtCertType ybMdtrtCertType ,
String busiCardInfo , Integer minpacuntDrugTracCnt , Integer mcsTracCnt ) {
PaymentResult paymentResult = null ;
if ( ! CommonConstants . BusinessName . DEFAULT_CONTRACT_NO . equals ( payTransNo ) ) {
if ( ! ( CommonConstants . BusinessName . DEFAULT_CONTRACT_NO . equals ( payTransNo )
| | CommonConstants . BusinessName . DEFAULT_STUDENT_CONTRACT_NO . equals ( payTransNo ) ) ) {
// 医保支付 todo: 支付的详细信息在于结算中已经存好了, 但是还没有存储卡余额
Clinic2207OrderModel clinic2207OrderModel =
ybManager . settle ( contract , payTransNo , busiCardInfo , ybMdtrtCertType , minpacuntDrugTracCnt , mcsTracCnt ) ;
@@ -272,6 +400,21 @@ public class PaymentReconciliationServiceImpl extends ServiceImpl<PaymentReconci
. eq ( PaymentReconciliation : : getDeleteFlag , DelFlag . NO . getCode ( ) ) . last ( YbCommonConstants . sqlConst . LIMIT1 ) ) ;
}
/**
* 查询已收费付款实体
*
* @param encounterId 就诊id
* @return 付款实体
*/
@Override
public List < PaymentReconciliation > getListByEncounterId ( Long encounterId , PaymentKind paymentKind ) {
return baseMapper . selectList ( new LambdaQueryWrapper < PaymentReconciliation > ( )
. eq ( PaymentReconciliation : : getEncounterId , encounterId )
. in ( PaymentReconciliation : : getStatusEnum , PaymentStatus . SUCCESS . getValue ( ) , PaymentStatus . REFUNDING . getValue ( ) )
. eq ( PaymentReconciliation : : getKindEnum , PaymentKind . HOSPITAL_DEPOSIT . getValue ( ) )
. eq ( PaymentReconciliation : : getDeleteFlag , DelFlag . NO . getCode ( ) ) ) ;
}
/**
* 判断是否已退费
*
@@ -309,4 +452,181 @@ public class PaymentReconciliationServiceImpl extends ServiceImpl<PaymentReconci
return baseMapper . getPaymentAccountContract ( startTime , endTime , entererId , contractNo , success , returnAll ,
clinic ) ;
}
/**
* 查询自付比例等
*
* @param paymentedItemList 收款明细
* @return 学生付款实体
*/
private List < StudentPaymentItemModel > getStudentPaymentItemModelList ( List < PaymentedItemModel > paymentedItemList ) {
// 大项比例
List < GfTypeRatioDto > typeRatioList = gfRatioService . getTypeRatioList ( ) ;
Map < String , Map < String , List < GfTypeRatioDto > > > result = typeRatioList . stream ( ) . collect (
// 第一次分组:按 ybClass 分组(外层 key 为 ybClass)
Collectors . groupingBy ( GfTypeRatioDto : : getYbClass ,
// 第二次分组:对每个分组的 List 再按 subType 分组(内层 key 为 subType)
Collectors . groupingBy ( GfTypeRatioDto : : getYbLv ) ) ) ;
List < StudentPaymentItemModel > allPaymentItemList = new ArrayList < > ( ) ;
Map < String , List < PaymentedItemModel > > paymentedItemListByServiceTableMap =
paymentedItemList . stream ( ) . collect ( Collectors . groupingBy ( PaymentedItemModel : : getServiceTable ) ) ;
for ( Map . Entry < String , List < PaymentedItemModel > > stringListEntry : paymentedItemListByServiceTableMap
. entrySet ( ) ) {
String key = stringListEntry . getKey ( ) ;
ItemType itemType ;
if ( CommonConstants . TableName . MED_MEDICATION_REQUEST . equals ( key ) ) {
itemType = ItemType . MEDICINE ;
} else if ( CommonConstants . TableName . WOR_SERVICE_REQUEST . equals ( key ) ) {
itemType = ItemType . ACTIVITY ;
} else {
throw new ServiceException ( " 除药品和诊疗项目外不存在其他公费项目,请确认! " ) ;
}
List < PaymentedItemModel > value = stringListEntry . getValue ( ) ;
List < StudentPaymentItemModel > paymentItemList = gfRatioService . getGfRatioList ( itemType , value ) ;
for ( StudentPaymentItemModel studentPaymentItemModel : paymentItemList ) {
// 如果自付比例有值, 就continue掉
if ( studentPaymentItemModel . getSelfRatio ( ) ! = null & & studentPaymentItemModel . getTwiceRatio ( ) ! = null ) {
continue ;
}
// 查定价分类
ChargeItemDefinition chargeItemDefinition =
chargeItemDefinitionService . getById ( studentPaymentItemModel . getDefinitionId ( ) ) ;
// 查医保等级
if ( CommonConstants . TableName . ADM_DEVICE_DEFINITION . equals ( studentPaymentItemModel . getProductTable ( ) ) ) {
DeviceDefinition deviceDefinition =
deviceDefinitionService . getById ( studentPaymentItemModel . getProductId ( ) ) ;
if ( deviceDefinition ! = null & & chargeItemDefinition ! = null ) {
// 约定大项目的自付比例获取条件
YbMedChrgItmType medChrgItmType = YbMedChrgItmType . getByValue ( chargeItemDefinition . getYbType ( ) ) ;
if ( medChrgItmType = = null ) {
throw new ServiceException ( chargeItemDefinition . getChargeName ( ) + " 未配置正确的医保分类!请检查!!! " ) ;
}
YbChrgitmLv chrgitmLv = YbChrgitmLv . getByValue ( deviceDefinition . getChrgitmLv ( ) ) ;
if ( chrgitmLv = = null ) {
throw new ServiceException ( chargeItemDefinition . getChargeName ( ) + " 未配置正确的医保等级!请检查!!! " ) ;
}
List < GfTypeRatioDto > gfTypeRatioDtos =
result . get ( chargeItemDefinition . getYbType ( ) ) . get ( chrgitmLv . getCode ( ) ) ;
if ( gfTypeRatioDtos = = null | | gfTypeRatioDtos . isEmpty ( ) ) {
throw new ServiceException (
" 医保分类: " + medChrgItmType . getInfo ( ) + " 医保等级: " + chrgitmLv . getInfo ( ) + " 未配置自付比例!请检查!!! " ) ;
}
studentPaymentItemModel . setSelfRatio ( gfTypeRatioDtos . get ( 0 ) . getSelfRatio ( ) ) ;
studentPaymentItemModel . setTwiceRatio ( gfTypeRatioDtos . get ( 0 ) . getSelfRatio ( ) ) ;
}
} else if ( CommonConstants . TableName . WOR_ACTIVITY_DEFINITION
. equals ( studentPaymentItemModel . getProductTable ( ) ) ) {
ActivityDefinition activityDefinition =
activityDefinitionService . getById ( studentPaymentItemModel . getProductId ( ) ) ;
if ( activityDefinition ! = null & & chargeItemDefinition ! = null ) {
// 约定大项目的自付比例获取条件
YbMedChrgItmType medChrgItmType = YbMedChrgItmType . getByValue ( chargeItemDefinition . getYbType ( ) ) ;
if ( medChrgItmType = = null ) {
throw new ServiceException ( chargeItemDefinition . getChargeName ( ) + " 未配置正确的医保分类!请检查!!! " ) ;
}
YbChrgitmLv chrgitmLv = YbChrgitmLv . getByValue ( activityDefinition . getChrgitmLv ( ) ) ;
if ( chrgitmLv = = null ) {
throw new ServiceException ( chargeItemDefinition . getChargeName ( ) + " 未配置正确的医保等级!请检查!!! " ) ;
}
List < GfTypeRatioDto > gfTypeRatioDtos =
result . get ( chargeItemDefinition . getYbType ( ) ) . get ( chrgitmLv . getCode ( ) ) ;
if ( gfTypeRatioDtos = = null | | gfTypeRatioDtos . isEmpty ( ) ) {
throw new ServiceException (
" 医保分类: " + medChrgItmType . getInfo ( ) + " 医保等级: " + chrgitmLv . getInfo ( ) + " 未配置自付比例!请检查!!! " ) ;
}
studentPaymentItemModel . setSelfRatio ( gfTypeRatioDtos . get ( 0 ) . getSelfRatio ( ) ) ;
studentPaymentItemModel . setTwiceRatio ( gfTypeRatioDtos . get ( 0 ) . getSelfRatio ( ) ) ;
}
} else if ( CommonConstants . TableName . MED_MEDICATION_DEFINITION
. equals ( studentPaymentItemModel . getProductTable ( ) ) ) {
MedicationDefinition medicationDefinition =
medicationDefinitionService . getById ( studentPaymentItemModel . getProductId ( ) ) ;
if ( medicationDefinition ! = null & & chargeItemDefinition ! = null ) {
// 约定大项目的自付比例获取条件
YbMedChrgItmType medChrgItmType = YbMedChrgItmType . getByValue ( chargeItemDefinition . getYbType ( ) ) ;
if ( medChrgItmType = = null ) {
throw new ServiceException ( chargeItemDefinition . getChargeName ( ) + " 未配置正确的医保分类!请检查!!! " ) ;
}
YbChrgitmLv chrgitmLv = YbChrgitmLv . getByValue ( medicationDefinition . getChrgitmLv ( ) ) ;
if ( chrgitmLv = = null ) {
throw new ServiceException ( chargeItemDefinition . getChargeName ( ) + " 未配置正确的医保等级!请检查!!! " ) ;
}
List < GfTypeRatioDto > gfTypeRatioDtos =
result . get ( chargeItemDefinition . getYbType ( ) ) . get ( chrgitmLv . getCode ( ) ) ;
if ( gfTypeRatioDtos = = null | | gfTypeRatioDtos . isEmpty ( ) ) {
throw new ServiceException (
" 医保分类: " + medChrgItmType . getInfo ( ) + " 医保等级: " + chrgitmLv . getInfo ( ) + " 未配置自付比例!请检查!!! " ) ;
}
studentPaymentItemModel . setSelfRatio ( gfTypeRatioDtos . get ( 0 ) . getSelfRatio ( ) ) ;
studentPaymentItemModel . setTwiceRatio ( gfTypeRatioDtos . get ( 0 ) . getSelfRatio ( ) ) ;
}
} else {
HealthcareService healthcareService =
healthcareServiceService . getById ( studentPaymentItemModel . getServiceId ( ) ) ;
if ( healthcareService ! = null & & chargeItemDefinition ! = null ) {
// 约定大项目的自付比例获取条件 医疗服务没有定义医保等级,默认百分百还是直接抛异常?
studentPaymentItemModel . setSelfRatio ( new BigDecimal ( " 100 " ) ) ;
studentPaymentItemModel . setTwiceRatio ( new BigDecimal ( " 100 " ) ) ;
}
}
allPaymentItemList . addAll ( paymentItemList ) ;
}
}
return allPaymentItemList ;
}
/**
* 医保预结算
*
* @param contract 合同b
* @param ybMdtrtCertType 证件类型
* @param busiCardInfo 电子密钥
* @param paymentedItemList 收款明细
* @return 预结算参数
*/
private PrePaymentResult studentPreSettleYb ( Contract contract , YbMdtrtCertType ybMdtrtCertType , String busiCardInfo ,
List < PaymentedItemModel > paymentedItemList ) {
Map < String , List < PaymentedItemModel > > collect =
paymentedItemList . stream ( ) . collect ( Collectors . groupingBy ( PaymentedItemModel : : getMedType ) ) ;
// 一次医保结算只能支持一种医疗类型的结算
for ( Map . Entry < String , List < PaymentedItemModel > > medTypeKV : collect . entrySet ( ) ) {
Clinic2206OrderOutput clinic2206OrderOutput = null ;
ClinicReg2201Output reg2201Output = null ;
if ( ! medTypeKV . getKey ( ) . equals ( YbMedType . GENERAL_OUTPATIENT . getValue ( ) ) & & " 1 "
. equals ( SecurityUtils . getLoginUser ( ) . getOptionJson ( ) . getString ( CommonConstants . Option . YB_SWITCH ) ) ) {
// 不是普通门诊就诊类型,补充挂号信息
reg2201Output = ybManager . createRegWithMedType ( contract , ybMdtrtCertType , busiCardInfo ,
medTypeKV . getValue ( ) . get ( 0 ) . getEncounterId ( ) ,
YbMedType . getByValue ( medTypeKV . getValue ( ) . get ( 0 ) . getMedType ( ) ) ) ;
reg2201Output . setMedType ( medTypeKV . getKey ( ) ) ; // 2025/06/05慢病挂号后上传2206信息报错, 2201返回值没有medType, 此处更正赋值
} else {
// 从数据库里取reg2201
reg2201Output = ybManager . getClinicRegByEncounterId ( medTypeKV . getValue ( ) . get ( 0 ) . getEncounterId ( ) ) ;
}
if ( reg2201Output = = null ) {
throw new ServiceException ( " 未查询到医保挂号信息 " ) ;
}
// 调用预结算
clinic2206OrderOutput =
ybManager . preSettle ( contract , medTypeKV . getValue ( ) . get ( 0 ) . getEncounterId ( ) , ybMdtrtCertType ,
busiCardInfo , reg2201Output , " 01 " , medTypeKV . getValue ( ) , YbMedType . getByValue ( medTypeKV . getKey ( ) ) ) ;
PrePaymentResult prePaymentResult = new PrePaymentResult ( ) ;
BeanUtils . copyProperties ( clinic2206OrderOutput , prePaymentResult ) ;
return prePaymentResult ;
}
return null ;
}
}